如何在 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 <= testpos < limit
,即使长度是可能的最大整数值,它也可以工作。
这种形式还可以很容易地读取您想要查看的不变量,而无需考虑像high<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 中简化这个工作的二进制搜索代码?的主要内容,如果未能解决你的问题,请参考以下文章