编辑 这是被接受的,所以我想我真的应该试着把它变成一个正确的答案。
我最初假设(请参阅下面的“注意”)问题是使用半开边界。它实际上(正确地)使用了包容性边界。在最初的通话中,low=0
和high=n-1
.
使用包容性边界通常被认为是一件坏事 - 请参阅 Dijkstra 的经典著作 (PDF)。在 C 系列语言中,半开边界是一种常见的约定,甚至是对for (i = 0; i < n; i++)
over的偏好for (i = 0; i <= n-1; i++)
。但是,鉴于使用了包含边界,问题中的代码似乎是正确的。
然而,正如 WhozCraig 在评论中所发现的那样,调用代码不遵守该约定,并且传递了错误的边界 - 包括搜索范围内的越界垃圾项。因为那个额外的项目是垃圾,所以范围内的项目已排序的假设也可能无效。大多数搜索不会找到该垃圾项(因为您不太可能搜索它具有的任何垃圾值),但它会误导搜索。
注意 这可能不是答案,但评论太长了。
你的界限是包容的、排他的还是半开放的?
我将假设 半开放 - 包含 at low
,独占 at high
。如果是这样,这条线看起来是错误的......
if (target < * (oringalary + mid))
return recurbinarysearch(oringalary, low, mid - 1, target);
原因是您已在 处检查了该项目mid
,但您将mid - 1
其用作新的专属上限。这意味着mid - 1
未检查的位于 的项目已意外从搜索中排除。线路应该...
if (target < * (oringalary + mid))
return recurbinarysearch(oringalary, low, mid, target);
这将项目保持mid - 1
在要搜索的范围内。mid
由于上限是独占的,因此不会再次搜索该项目。
在二进制搜索中搞乱界限是一个常见问题,它会导致比看起来应该的错误更多。
但是,这本身并不能解释您的症状 - 它有时应该无法找到项目(可能大约 50% 的搜索),但它不应该为成功的搜索报告错误的位置。
二进制搜索中错误边界的常见症状是无限循环(同一项目被重复检查,因为它没有被排除在边界之外)或搜索未能找到存在的项目(因为项目被排除在搜索范围之外)检查)。
老实说,我看不出你的症状是如何发生的。函数退出的所有可能方式都应该给出正确的成功结果,否则给出-1
失败结果。我能想到的唯一可能的例外是在这段代码之外——误解了结果,例如未能检查-1
结果。
顺便说一句 - 这是我代表我的问题和回答关于一次比较每次迭代二分搜索的绝佳机会。
编辑我想我发现了边界的另一个问题 - 仍然假设半开,这条线是错误的......
if (low > high) {
并且应该...
if (low >= high) {
原因是对于半开边界,如果边界相等,则中间没有要检查的项目——即使是下限项目也是无效的,因为上限等于它并且是互斥的。这使您仍然可以测试