折半查找这种思想其实我们之前就已经接触过挑战408——数据结构(20)——二叉搜索树(BST)。这里我们同样采用相同的方式来实现在顺序表中是怎么使用这种思想来查找的。
一个数组查询的实例
查找问题,可以简单理解为我们有大量的数据,我们怎么样可以在这大量的数据中快速找到需要的数据?
假设我们有一个已经排好序的数组:
那么在这个数组中,查到我们需要的数据需要多长时间?显然,如果我们从头开始并向前查找,那么每检查的一个项目就可以排除1个项目,最坏的情况就是我们需要从头到尾遍历完所有的数组中的数据。
相反,如果我们直接从中间开始查询,那么会有三种情况发生:
- 中间的数据恰好是我们要寻找的数字。(假如我们要寻找元素29)
- 我们意识到我们离要寻找的元素走得太远了。(假如我们要寻找元素7)
- 我们意识到我们还离要寻找的元素还很远。(假如我们要寻找元素90)
现在我们选择情况3讨论:离要寻找的元素还很远。
这种情况,我们至少排除了整个上半部分,现在只需要搜索下半部分。我们可以从下半部分的开头开始,然后依次遍历剩余的元素…,但是我们为什么又要依次遍历呢?明明我们可以采用刚刚的方式,直接跳到中间搜索啊。
如此反复上述操作,便可以事半功倍的完成查询操作!
折半查找法的实现
下面的实现方法,在之前写的折半查找也有,只不过返回类型不同罢了。
我们需要在一个已经排序的vector中找到某个值,于是函数的声明应该是这样的:
//也可以定义为int类型
bool binarySearch(const Vector<int>& data, int key) ;
具体的实现方式其实很简单:
bool binarySearch(const Vector<int>&data ,int key,int start,int end){
if(start > end){
return false;
}
int mid = (start + end)/2;
if(key == data[mid]){
return true;
}else if(key < data[mid]){ //在中间
return binarySearch(data,key,start,mid-1);
}else{
return binarySearch(data,key,maid -1,end);
}
排序与查找
那么言归正传,排序与查找之间是否存在联系呢?答案是肯定的,不然我也不会放在一起写。总的来说,排序方便查找,有时候可以大大的降低查找的时间。我们上课的时候老师特意给我们举过一个简单的例子:当你的数据库的记录太多的时候,一定要进行排序。为什么呢?
假设你的数据库有10,000,000条记录,倘若你不对数据进行排序后再查找,那么你的平均查找次数是(10,000,000 / 2)次。如果我们将数据进行过排序(假设是升序排序),那么利用折半查找法,可以在
2
n
2^{n}
2n = 10,000,000 次下找到对应的数值。于是平均只需进行10几次(即N的值)的搜索,便可以确定我们的数值。速度提升了好几个数量级。
所以我们在数据库设计的时候,如果数据量庞大,那么尽量对数据先排序处理。