考虑下面的Binary Search函数的C实现,这有什么问题吗?
// A iterative binary search function. It returns location of x in
// given array arr[l..r] if present, otherwise -1
int binarySearch(int arr[], int l, int r, int x)
{
while (l <= r)
{
// find index of middle element
int m = (l+r)/2;
// Check if x is present at mid
if (arr[m] == x) return m;
// If x greater, ignore left half
if (arr[m] < x) l = m + 1;
// If x is smaller, ignore right half
else r = m - 1;
}
// if we reach here, then element was not present
return -1;
}
除了一个微妙的东西,即“ m =(l + r)/ 2”,上述内容看起来还不错。对于l和r较大的值,它将失败。特别是,如果low和high的总和大于最大正整数值(2 31 – 1),它将失败。该总和溢出为负值,并且该值在被二除时保持为负。在C语言中,这会导致数组索引超出范围,从而导致无法预测的结果。
解决此问题的方法是什么?
以下是一种方法:
int mid = low + ((high - low) / 2);
可能更快,并且可以说是清楚的(仅在Java,请参阅此内容):
int mid = (low + high) >>> 1;
在C和C++(其中没有>>>运算符)中,可以执行以下操作:
mid = ((unsigned int)low + (unsigned int)high)) >> 1
合并排序中也会出现类似的问题。
以上内容摘自google reasearch博客。
请同时参考,它指出上述解决方案可能并不总是有效。
当数组长度为2 30或更大,并且搜索反复移动到数组的后一半时,会发生上述问题。这么大的数组不太可能在大多数时间出现。例如,当我们尝试使用32位代码块编译器的以下程序时,会出现编译器错误。
int main()
{
int arr[1<<30];
return 0;
}
输出:
error: size of array 'arr' is too large
即使我们尝试使用布尔数组,该程序也可以正常编译,但是在Windows 7.0和Code Blocks 32位编译器中运行时会崩溃
#include
int main()
{
bool arr[1<<30];
return 0;
}
输出:没有编译器错误,但是在运行时崩溃。
资料来源:
http://googleresearch.blogspot.in/2006/06/extra-extra-read-all-about-it-nearly.html
http://locklessinc.com/articles/binary_search/