【发布时间】:2017-09-25 00:30:25
【问题描述】:
我正在研究二分搜索算法,我见过很多次这样写的算法(这是C++,但这里的语言不是那么重要):
int start = 0;
int end = vec.size() - 1;
do {
int mid = (lo + hi) / 2;
if (target < vec[mid])
start = mid + 1;
else if (target > vec[mid])
end = mid - 1;
else
// found
} while (start <= end);
不过我也见过这样的实现:
int start = 0;
int end = vec.size() - 1;
do {
int mid = (int)ceil((lo + hi) / 2.0);
if (target < vec[mid])
start = mid + 1;
else if (target > vec[mid])
end = mid - 1;
else
// found
} while (start <= end);
两者似乎都有效。我应该得到ceil 并执行第二种情况的浮点运算而不是使用第一个版本,是否有任何正确性或性能原因?
【问题讨论】:
-
注意
(lo + hi + 1) / 2可以避免浮点数。 -
我想这基本上在这里得到了回答:stackoverflow.com/questions/27655955/…(因此很想标记为重复)。
-
请注意,您的中点公式错误,因为
left + right有溢出的风险。更好的做法是:(int)(((unsigned)lo + (unsigned)hi) / 2),它为您提供了所需的二进制补码环绕行为。 (另请参阅this answer,尽管它是在 C# 的上下文中。有关此的大量信息可通过 Google 在线获取。) -
@CodyGray:实际上,制作索引
unsigned(或者更好的是,size_t)从一开始就是合乎逻辑的事情做... -
Kaidul 的回答是正确的,但见stackoverflow.com/questions/39416560/…
标签: c++ algorithm binary-search