The C Programming Language book by Dennis M. Ritchie and Brian W. Kerninghan的第this example节(第3.3节)中,我认为这段代码有问题,确实当我运行它时,它确实没有像预期的那样工作.

以下是书中的原始代码:

/* 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中,否则它可以正常工作,但一个好的程序应该涵盖所有情况),解决这个问题的方法是删除测试中的"or equals"部分,这意味着将其更改为low < high.第二个错误是第一个if语句,因为当它发现x < v[mid]时,它将high设置为mid + 1,这显然是错误的,因为如果x值小于中间值(v数组已排序),那么x将在小于中间索引的索引中,因此我们应该判断的范围是0mid -1,但情况并非如此,因为在书中,他们将MID和MID+1包括在我们知道它们大于x的范围内(因为x&lt;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循环的返回值吗?

推荐答案

第一版K&;R似乎包含以下代码,这些代码确实存在错误,可能会永远循环:

/* 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; /* bug here */
        else if (x > v[mid])
            low = mid + 1;
        else /* found match */
            return mid;
    }
    return -1; /* no match */
}

《K&;R》第二版包括以下更正版本:

/* 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; /* correction here */
        else if (x > v[mid])
            low = mid + 1;
        else /* found match */
            return mid;
    }
    return -1; /* no match */
}

C++相关问答推荐

getchar读css + z还是返回css?

ZED for SDL上的C语言服务器

C中的指针增量和减量(*--*++p)

进程在写入管道时挂起

在循环中复制与删除相同条件代码的性能

是否可以通过调用两个函数来初始化2D数组?示例:ARRAY[STARTING_ROWS()][STARTING_COLUMNS()]

为什么我的Hello World EFI程序构建不正确?

如何用c语言修改shadow文件hash部分(编程)?

GCC错误,共享内存未定义引用?

链接器脚本和C程序使用相同的头文件,这可能吗?

C标准关于外部常量的说明

对于STM32微控制器,全局偏移表.get和.Got.plt必须为零初始化

如果类型是新的,offsetof是否与typeof一起工作?

如何使crc32的结果与cksum匹配?

C 程序不显示任何输出,但它接受 CS50 Lab1 的输入问题

C 语言中 CORDIC 对数的问题

函数指针作为函数参数 - 应该使用 const 吗?

UEFI 应用程序中的计时器回调仅在 AMI BIOS 中挂起

为什么实现文件中的自由函数默认没有内部链接?

多行表达式:C 编译器如何处理换行符?