很久以前在csdn的编码挑战栏里第一次看到“90%的程序员无法正确实现二分查找”这种挑衅性的论断,那时候我还是个算法盲,基本二分查找也只是听说而已,但还是对此深表怀疑。出于各种原因也没有动手试一试。
近期开始练基本功,到查找这一块时,特别留意了下这个话题,原来出自《编程珠玑》、《计算机程序设计艺术》等大师经典,像《编程之美》等也都有所提及。所以特别在标题中加了“传说”二字。
试了一试,果真很多坑,比如源数据为空如何处理?待查数据范围正确,但其实查不到的情况程序会得到什么结果?
类似的问题这篇文章总结的算是可以了,我这里就不献丑了。
以下是我自己的代码,一开始习惯用递归,不过参数用vector时,递归要做许多无谓的截断工作,效率应该极低,索性就不递归了。
和流传的“标准”略有不同,不过无伤大雅了。不敢说没问题,假如有热心大牛帮忙指出bug,感激不尽。
#include <iostream>
#include <vector>
using std::cin;
using std::cout;
using std::endl;
using std::vector;
//在有序vector中二分查找target,返回下标值,若找不到,返回-1
int binary_search(vector<int> src, int target)
{
int n = src.size();
if (0 == n)
{
return -1;
}
if ((target > src[n-1]) || (target < src[0]))
{
return -1;
}
int left = 0;
int right = n-1;
int mid = left + (right - left)/2;
while (src[mid] != target)
{
if (src[mid] < target)
{
left = mid + 1;
}
else if (src[mid] > target)
{
right = mid -1;
}
if (left > right)
{
return -1;
}
mid = left + (right - left)/2;
}
return mid;
}
int main()
{
vector<int> src;
cout<<"请输入整形数组:";
int temp;
while (cin>>temp)
{
src.push_back(temp);
}
cin.clear();
cin.sync(); //需清缓冲,否则无法二次使用cin
int target;
cout<<"请输入需查找数:";
cin>>target;
cout<<"查找所得下标为:"<<binary_search(src, target)<<endl;
}
总体来说研究过这个话题之后,在对程序正确性的认识上还是自感深刻了不少的,可以想象我之前做的那些工程、贴的那些代码,不知隐藏着多少bug。
但是无所谓了,不可因噎废食,只能以后在这方面尽量多注意吧。
另外提下:
静态查找不光只有二分查找一种,其他还有斐波纳契查找、插值查找等,基本大同小异,只是每次截断的比例点有所不同,传说性能上多少有些差异,这里就暂不深究了。