【问题标题】:Why doesn't my binary search implementation find the last element?为什么我的二进制搜索实现找不到最后一个元素?
【发布时间】:2017-08-12 00:21:06
【问题描述】:

我已经在 C 中实现了二进制搜索的初学者递归版本。但是,当要找到的元素位于数组的最后位置时,它似乎不起作用。有没有办法在不改变函数原型的情况下解决这个问题?

#include <stdio.h>

int search(int value, int values[], int n);

int main() {
    int a[] = { 26, 27, 28 };

    if (search(28, a, 3) == 0)
        printf("Found.\n");
    else
        printf("Not found.\n");
}

int search(int value, int values[], int n)
{
    if (n <= 0) 
        return 1;

    if (value < values[n/2])
        // Search the left half
        return search(value, values, n/2);
    else if (value > values[n/2])
        // Search the right half, excluding the middle term
        return search(value, values + n/2 + 1, n/2 - 1);
    else 
        return 0;

    return 1;
}

【问题讨论】:

  • 我刚刚运行了你的代码;它工作正常吗?你能澄清你的错误,你的可重现步骤吗?
  • 如果value == values[n/2],你为什么要返回0?你不应该返回n/2 吗?而return 1 行也没用。
  • 如果 N 为 3,你认为 n/2 - 1 会是什么?
  • n/2 - 1 --> n - n/2 - 1

标签: c arrays binary-search


【解决方案1】:

您的search 函数不正确:

  • 在右侧部分递归时传递的切片大小计算不正确:它应该是 n - n/2 - 1 而不是 n/2 - 1

这是一个更正的版本:

#include <stdio.h>

int search(int value, int values[], int n);

int main(void) {
    int a[] = { 26, 27, 28 };

    if (search(28, a, 3) == 0)
        printf("Found.\n");
    else
        printf("Not found.\n");

    return 0;
}

int search(int value, int values[], int n) {
    if (n > 0) {
        int mid = n / 2;
        if (value < values[mid]) {
            // Search the left half
            return search(value, values, mid);
        } else
        if (value > values[mid]) {
            // Search the right half, excluding the middle term
            return search(value, values + mid + 1, n - mid - 1);
        } else {
            // Found the value
            return 0;
        }
    }
    return 1;
}

这是一个更简单的迭代版本:

int search(int value, int values[], int n) {
    while (n > 0) {
        int mid = n / 2;
        if (value < values[mid]) {
            // Search the left half
            n = mid;
        } else
        if (value > values[mid]) {
            // Search the right half, excluding the middle term
            values += mid + 1;
            n -= mid + 1;
        } else {
            // Found the value
            return 0;
        }
    }
    return 1;
}

【讨论】:

    【解决方案2】:

    这似乎是您在 else if 子句中的 return 语句。数组n 的长度应该是n-n/2-1 而不是n/2-1,否则最后一个元素将被剪掉。随着数组长度的增加以及您正在搜索来自右侧的元素,您可以看到这种情况更加普遍。

    return search(value, values + n/2 + 1, n - n/2 - 1);
    

    注意: 正如chqrlie指出的那样

    【讨论】:

    • @chqrlie 这是一个很好的观点,也是一个重要的观点。尽管我将把它留给 OP 自行决定,因为主要关注点似乎是数学逻辑。
    • @chqrlie 实际上,这将解决越界问题,很好。
    猜你喜欢
    • 2016-07-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-09-26
    相关资源
    最近更新 更多