在Dennis M.里奇和布赖恩W. Kerninghan*,我认为这段代码有问题,实际上当我运行它时,它确实没有按预期工作。
下面是书中的原始代码:
/* binsearch: find x in v[0] <= v[1] <= ... <= v[n-1] */
int binsearch(int x, int v[], int n)
{
int low, high, mid;
low = 0;
high = n - 1;
while (low <= high) {
mid = (low+high)/2;
if (x < v[mid])
high = mid + 1;
else if (x > v[mid])
low = mid + 1;
else /* found match */
return mid;
}
return -1; /* no match */
}
所以,这个函数应该在一个整数数组中搜索一个整数,如果找到了,函数将返回它的位置,否则将返回-1。第一个明显的错误是wile循环中的测试low <= high
,它在这个函数中总是保持True,因此这个循环将无限运行,永远不会结束(这就是我运行它时发生的事情,它显然陷入了无限循环(编辑:如果x不在v中,否则它可以正常工作,但一个好的程序应该涵盖所有情况)),解决这个问题的方法是删除测试的“或等于”部分,这意味着将其更改为low < high
。第二个错误是第一个if
语句,因为当它发现x < v[mid]
时,它将high
设置为mid + 1
,这显然是错误的,因为如果x值小于中间值(v数组被排序)那么x将在小于中间索引的索引中,因此我们应该检查的范围将是0
到mid -1
,但情况并非如此,因为在书中,他们包括了mid和mid + 1的范围,我们知道他们大于x(因为x < v[mid]),所以他们应该设置为mid - 1
。
所以我的问题是在这个例子中,他们真的犯了一个错误,还是我误解了?如果他们这样做了,我所说的错误是正确的还是错误的?最后,下面是函数的实现,沿着,以及我在上面的C代码中所述的更正(当我执行它时,它按预期工作):
#include <stdio.h>
int binsearch(int x, int v[], int n);
int main() {
int n = 10, x = 25;
int v[10] = {0, 5, 10, 19, 20, 21, 22, 23, 25, 70};
int position = binsearch(x, v, n) + 1;
if (position) /*equivalent to (position != 0) since position will equal 0 when binsearch returns -1*/
printf("x is at: %d", position);
else
printf("x is not found.");
return 0;
}
int binsearch(int x, int v[], int n) {
int low, high ,mid;
low = 0;
high = n - 1;
while (low < high) {
mid = (low + high) / 2;
if (x < v[mid])
high = mid - 1;
else if (x > v[mid])
low = mid + 1;
else /* found match */
return mid;
}
return -1; /* no match */
}
最后一个问题,当x确实在v中时,在最后会找到相应的索引,它会在return mid;
语句中返回,但是当我们离开while循环时,我们发现-1也会返回,这不会覆盖while循环的返回值吗?
2条答案
按热度按时间a5g8bdjr1#
K&R的第1版似乎包括以下代码,这些代码确实存在漏洞,并且可以永远循环:
K&R第二版包括以下更正版本:
6rqinv9w2#
最后一个问题,当x确实在v的末尾时,相应的索引将被找到,它将在返回mid中返回;但是当我们离开while循环时,我们发现-1也会被返回,这不会覆盖while循环的返回值吗?
不,当函数到达
return
语句时,它终止执行并返回给调用者。你误解了函数的工作原理。当你在火车上时,你把它放在A站。火车继续开往B站。你能把它放在那里吗?不-因为你已经不在火车上了。