如何解决以下两种二分查找实现的性能差异
我在“Competitive Programmer's Handbook”https://cses.fi/book/book.pdf一书中遇到过这两种二分搜索实现。
方法一:
int a = 0,b = n-1;
while (a <= b) {
int k = (a+b)/2;
if (array[k] == x) {
// x found at index k
}
if (array[k] > x)
b = k-1;
else
a = k+1;
}
方法 2:
int k = 0;
for (int b = n/2; b >= 1; b /= 2){
while (k+b < n && array[k+b] <= x)
k += b;
}
if (array[k] == x){
// x found at index k
}
我猜方法 2 不完全是二分搜索。 我知道 method 1 和 method 2 都有 O(log n) 复杂度。此外,方法 2 的代码更简单,因此可能会导致更少的错误。
我的问题是:
解决方法
对于这么短的代码和这么少的差异,无法做任何预测。时间性能将取决于编译器的优化方式,还取决于数组中键的分布(特别是命中而不是未命中的概率)。
我不同意“反对”第二种方法的所有评论(甚至在完全正确的情况下声称有缺陷)。它基于一个可能使它变得更好的原则:循环体中只有一个测试。
进行相等性比较(方法 1)会给人一种错误的感觉,即算法将在找到密钥时提前终止并加快搜索速度*。但事实并非如此,因为对于一半的键,决策树的完整深度无论如何都是必要的,而且这并没有被两个比较而不是一个比较这一事实所抵消。
*事实上,您平均只需一次测试!
只有基准测试才能告诉您其中一种方法对于特定测试用例是否更快。我敢打赌,运行时间的分布有很多重叠。 (不算,实际上不可能以代表其在实际环境中的行为的方式对如此快速的算法进行基准测试。)
最后评论:方法2是二元搜索,而实际上方法1是三元!
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。