如何在 C 中简化这个工作的二进制搜索代码?

Posted

技术标签:

【中文标题】如何在 C 中简化这个工作的二进制搜索代码?【英文标题】:How can I simplify this working Binary Search code in C? 【发布时间】:2017-01-17 21:34:24 【问题描述】:

大家好,几个星期前开始使用 C 进行编程,学习算法,只是想知道如何让我的代码更简单,它只是一个二进制搜索功能。但唯一的问题是你必须保持参数不变,提前谢谢。

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

    int min = values[0];
    int max = values[n-1];
    int average = (min + max) / 2;

    if(average == value)
    
        return true;
    

    while (average > value) 
    
        max = average - 1;
        average = (min + max) / 2;

    

    while (average < value)
    
        min = average + 1;
        average = (min + max) / 2;
    

    if (max < min) 
    
        return false;
    
    if (average == value) 
         printf("%i\n", average);
        return true;
    
    else
    
        return false;
    

【问题讨论】:

【参考方案1】:

在二分搜索中有很多小事情你必须做对:处理 length=0 的情况,确保你测试的位置总是有效的,确保你不会溢出(即,`(low +high)/2' 不是最好的写法),确保新的测试位置总是与前一个不同,等等。

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

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);

请注意,我们每次迭代只需要进行一次比较,这比大多数可以进行 2 次的实现要快。我们无需在循环内进行相等性测试,而是可靠地找到要查找的元素所属的位置,仅使用每次迭代进行一次比较,然后在最后进行测试以查看我们想要的元素是否存在。

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

这种形式还可以很容易地读取您想要查看的不变量,而无需考虑像high&lt;low 这样的奇怪边界条件。当您退出循环时,pos==limit 这样您就不必担心使用错误等等。

这个循环中的条件也很容易适应不同目的的二进制搜索,例如“找到插入 x 的位置,确保它在数组中已经存在的所有 xs 之后”,“找到 first x in the array”,“查找 last x in the array”等。

【讨论】:

你能解释一下(limit - pos) >> 1的意思吗? >> 1 是右移一位。它与除以二相同,向下舍入到最接近的整数,但在我学习的一些旧计算机上速度更快。它甚至对负数进行四舍五入,这使得它与整数除法不同,因此编译器不一定将 /2 优化为 >>1 ......但这并不重要。 pos + (limit-pos)/2 一样好。重要的部分是中间结果都不会溢出并给出错误的结果,如 (limit+pos)/2 可以。【参考方案2】:

这不是二分查找的正确实现,所有条件都必须在一个循环中,例如: 另外 max 必须是 n-1 而不是 values[n-1] 和 min=0 而不是 values[0] 因为您还应该将 values[average] 与 value 进行比较,而不仅仅是平均变量。

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

    int min = 0;
    int max = n-1;
    int average ;

    while(max>=min)
        average = (min + max) / 2;
        if(values[average] == value)
        
            return true;
        

        if (values[average] > value) 
        
            max = average - 1;
            average = (min + max) / 2;

        

       if (values[average] < value)
        
            min = average + 1;
            average = (min + max) / 2;
        

    

    return false;

【讨论】:

哇,你让它变得如此简单。我唯一的另一个问题是你为什么决定让它 if(values[average] 虽然行不通,但您需要创建一个循环并比较 values[average] 、 value 并更改循环的下一次重复的平均值,直到找到或未找到它。我刚刚看到我在上面的主while循环中忘记了一个while循环,这是错误的,它必须是if语句而不是while,我只是修复它看到编辑。

以上是关于如何在 C 中简化这个工作的二进制搜索代码?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 C 中的日期字符串中对字符串日期进行二进制搜索?

如何修复Code以使C#中的Fibonacci搜索算法正常 工作

如何在数据库索引中使用二进制搜索

如何在C中调用简化分数的函数?

Fortran 95 中的二进制搜索

如何显示(输出)在二进制搜索树中查找值所需的迭代次数?