在二进制搜索中,我们通常有低变量和高变量,通常有一个while循环测试低< =高,如此代码(来自维基百科)所示:
int SortedArray[max] = {....}
int BinarySearch (int key)
{
int start = 0;
int end = max - 1;
int mid;
while (start <= end)
{
mid = (start + end) / 2;
if (key == a[mid])
return mid;
else if (key < a[mid])
end = mid - 1;
else start = mid + 1;
}
return -1;
}
在学习二元搜索时,我总是被教导低等高的方法,但是当看到其他实现时,我已经看到很多人在做(低/高)。
一个与另一个相比有优势吗?在我自己的原生实现中,我执行&lt; =方法但是当我将其切换为&lt;时,搜索失败。
使用一个与另一个是否有经验法则吗?
答案 0 :(得分:6)
即使你的问题可能不是很清楚,我也可以推断你在谈论二元搜索的这种实现(这里是C,来自维基百科):
int SortedArray[max] = {....}
int BinarySearch (int key)
{
int start = 0;
int end = max - 1;
int mid;
while (start <= end)
{
mid = (start + end) / 2;
if (key == a[mid])
return mid;
else if (key < a[mid])
end = mid - 1;
else start = mid + 1;
}
return -1;
}
如果您将start <= end
替换为start < end
,则会出现您的算法无法给出正确答案的情况。
让我们考虑两个案例。
1 - 您想在列表[1]
中搜索1。在这种情况下,如果更改循环条件,start = 0, end = 0
和算法将返回-1。
2 - 您想在列表[1, 2]
中搜索2。在这种情况下,start = 0,end = 1.算法将在C中设置mid = (0+1)/2=0
。arr[mid] < key
。这将start = 1, end = 1
。同样,如果你在这里停止循环,算法将返回-1而不是1.
可能还有很多其他的例子。
度过愉快的一天
答案 1 :(得分:1)
对于low <= high
,high
被视为包含(high
是我们考虑范围的一部分。)
对于low < high
,high
被视为独占(high
不属于我们考虑范围的一部分。)
两者都可以是正确的,但其余代码会有细微的差别,特别是high
初始化的方式(high = length-1
与high = length
)以及如何更新({{ 1}}与high = mid-1
)。
哪一个更好?
主要区别在于high = mid
对于每种情况都会略有不同。
更具体地说,mid = (low + high) / 2
在排他性情况下会更大1,因此,当high
在包容性情况下,high-low
将保持不变,但{{1}时在包容性情况下是奇数,mid
在独占情况下将是1个元素更大(这是因为四舍五入)。
让我们考虑一个例子:
high-low
正如你所看到的,当没有单个中间元素时,一个将选择左边的元素,另一个将选择右边的元素。
虽然这有时会使一个更快,有时会使另一个更快,但平均运行时间将完全相同。
从可读性的角度来看,在我看来,使用基于0的数组的语言中的独占语言和基于1的数组的语言中的任何一个可能稍微好一点,以便最小化{{ 1}}在代码中。也可以争论只是坚持所有语言的单一版本,不要求人们理解这两个版本或在两者之间混淆。