有序向量二分查找
目录
版本一
版本二
版本三
版本一
#include <iostream>
using namespace std;
template <typename T>
static int binSearch(T* A, T const& e, int lo, int hi)
{
while (lo < hi)
{
int mi = (lo + hi) >> 1;
if (e < A[mi])
{
hi = mi;
}
else if (e > A[mi])
{
lo = mi + 1;
}
else
{
return mi;
}
}
return -1;
}
int main()
{
int arr[10] = { 0,1,2,3,4,5,6,7,8,9 };
int ret = binSearch<int>(arr, 5, 0, 10);
cout << "ret = " << ret << endl;
system("pause");
return 0;
}
运行结果:
缺点一:效率仍然可以优化,因为不难发现
转向左、右分支前的关键码比较次数不等,而递归深度却相同
缺点二:并未严格兑现search(e)接口"返回不大于e且秩最大的元素"的要求
1)当有多个命中元素时,必须返回最靠后者
2)失败时,应返回不大于(亦是小于)e的最大者
负无穷< e < V[lo]时,返回lo-1(左侧哨兵) V[hi-1] < e < 正无穷时,返回hi-1(右侧哨兵左邻)
返回目录
版本二
解决缺点一
#include <iostream>
using namespace std;
template <typename T>
static int binSearch(T* A, T const& e, int lo, int hi)
{
while (hi - lo > 1)
{
int mi = (lo + hi) >> 1;
(e < A[mi]) ? hi = mi : lo = mi;
}
return (e == A[lo]) ? lo : -1;
}
int main()
{
int arr[10] = { 0,1,2,3,4,5,6,7,8,9 };
int ret = binSearch<int>(arr, 5, 0, 10);
cout << "ret = " << ret << endl;
system("pause");
return 0;
}
运行结果:
如何更为精细地评估查找算法的性能?
考查关键码的比较次数,即查找长度(search length)
优点:此版本左、右分支前的关键码比较次数相等,最好情况下效率不如版本一; 作为补偿,最坏情况下效率有所提高
各种情况下的查找长度更加接近,整体性能更趋稳定
缺点:缺点二
返回目录
版本三
解决缺点一,缺点二
#include <iostream>
using namespace std;
template <typename T>
static int binSearch(T* A, T const& e, int lo, int hi)
{
while (lo < hi)
{
int mid = (lo + hi) >> 1;
(e < A[mid]) ? hi = mid : lo = mid + 1;
}
return --lo;
}
int main()
{
int arr[10] = { 0,1,2,3,4,5,6,7,8,9 };
int ret = binSearch<int>(arr, 5, 0, 10);
cout << "ret = " << ret << endl;
system("pause");
return 0;
}
运行结果: