我的代码中执行二进制搜索的错误在哪里?

时间:2016-07-08 03:22:36

标签: c algorithm binary-search cs50

我正在为二进制搜索算法编写代码。

代码:

#include "cs50.h"

int main(void) {
    int n = GetInt();
    int value = GetInt();
    int values[n];

    for (int i = 0; i < n; i++) {
        printf("Put in number %i ", i + 1);
        values[i] = GetInt();
    }

    int mid = (n - 1) / 2;
    int en = 0;
    int ex = n - 1;

    for (int i = 0, xt = i + 1; i < xt; i++) {
        if (value > values[mid]) {
            en = mid;
            mid = (en + ex) / 2;
        }
        else if (value < values[mid]) {
            ex = mid;
            mid = (en + ex) / 2;
        }
        else if (value == values[mid]) {
            printf("found");
            break;
        } else {
            printf("not found");
            break;
        }
    }
}

但它只有在找到的值位于中间某处时才有效。

在以下时间失败:

  1. 要找到的值是第一个或最后一个。
  2. 要找到的值不在输入的值中。
  3. 我真的无法弄清楚这个错误。

3 个答案:

答案 0 :(得分:4)

你需要在二进制搜索中找到一些小东西:处理长度= 0的情况,确保你测试的位置始终有效,确保你没有溢出(即,` (低+高)/ 2&#39;不是最好的写方式),确保新的测试位置总是与前一个不同,等等。

在完成了一百万次之后,我写的每个二进制搜索现在都是这样完成的:

bool search(int array[], int length, int valueToFind)
{
    int pos = 0;
    int limit = length;
    while(pos < limit)
    {
        int testpos = pos + ((limit - pos) >> 1);

        if (array[testpos] < valueToFind)
            pos = testpos + 1;
        else
            limit = testpos;
    }
    return (pos < length && array[pos] == valueToFind);
}

请注意,我们每次迭代只需要进行一次比较,这比其他答案中的搜索要快。我们不是在循环中进行相等测试,而是可靠地找到要查找的元素所在的位置,每次迭代只使用一次比较,然后在结束测试时查看我们想要的元素是否存在。

我们计算testpos的方式可以确保pos <= testpos < limit,即使长度是最大可能的整数值,它也能正常工作。

这种形式还可以很容易地读出你想要看到的不变量,而不必考虑像high<low这样奇怪的边界条件。当你走出循环时,pos==limit所以你不必担心使用错误的等等。

这个循环中的条件也很容易适应不同目的的二进制搜索,例如&#34;找到插入x的位置,确保它在已经在数组中的所有x之后#34;,&#34 ;在数组&#34;中找到第一个 x,&#34;在数组&#34;等中找到 last x。

答案 1 :(得分:2)

在我看来,for循环只会运行一次

for(int i = 0, xt = i + 1; i < xt; i++) {}

另外,为了使二进制搜索算法起作用,需要对整数列表进行排序。我不确定GetInt()究竟做了什么,但如果它返回一个随机值,那么也会导致搜索失败。

答案 2 :(得分:2)

  • 正如其他人所说,你在for循环中遇到了错误的条件。

  • 还有一个问题是

        if (value > values[mid])
        {
            en = mid;
            mid = (en+ex)/2;
        }
    
  • 此时(value > values[mid])您将en分配到mid+1,而mid必须分配,因为您必须在 {之后搜索元素{1}}

  • 类似地,如果(value < values[mid])ex必须分配mid-1 ,因为您必须搜索元素直到索引 {{1 小于 1

二进制搜索的更好实现如下:

  

注意:我分别使用midlow代替highen

ex

进行上述更改后,代码将为:

int mid; //no need to initialize as mid is initialized at the start of each iteration
int low = 0; //instead of en
int high = n-1; //instead of ex

while( low <= high )
{
    mid = low + ((high - low) / 2);; //updating mid value

    if (value > values[mid])
    {
        low = mid+1; //updating low
    }

    else if (value < values[mid])
    {
        high = mid-1; //updating high
    }

    else // if (value == values[mid])
    {
        printf("found"); //if found print 'found'
        break;
    }
}

if(low>high)
    printf("not found\n");

示例输入:

#include "cs50.h"
#include <stdio.h>

int main(void)
{
    int n = GetInt();
    int value = GetInt();

    if (n <= 0) 
    {
        //handle the error or exit
    }

    int values[n];

    for (int i=0;i<n;i++)
    {
        printf("Put in number %i \n",i+1);
        values[i]=GetInt();
    }

    int mid;
    int low = 0;
    int high = n-1;

    while( low <= high )
    {
        mid = low + ((high - low) / 2);

        if (value > values[mid])
        {
            low = mid+1;
        }
        else if (value < values[mid])
        {
            high = mid-1;
        }
        else 
        {
            printf("found");
            break;
        }
    }
    if(low>high)
        printf("not found\n");

}

示例输出:

5 //n
5 //value
1 2 3 4 5 //array elements

进一步阅读,请阅读:click