本篇文章可能只适用于刚刚接触二分查找算法的小白
一、二分查找
二分查找又名折半查找,是一种效率较高的查找方法。但二分查找要求线性表必须是顺序存储结构,且表中元素按关键字有序排列。
二、二分查找过程
从表的中间记录开始,先将线性表的中间元素的关键字与我们需要查找的给定关键字进行比较,如果给定关键字和中间记录的元素关键字相同,则查找成功;如果给定关键字比中间记录的关键字小,则往表的左边继续查找;如果给定关键字比中间记录的关键字大,则往表的右边继续查找。这样反复进行比较,直到查找成功,或着确认查找失败为止。
下面为演示过程:
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
5 | 13 | 19 | 21 | 37 | 56 | 64 | 76 | 80 | 88 | 92 |
给定关键字 21,上面为有序表arr
在二分查找算法中,我们需要通过循环来逐步缩小查找范围,直到找到目标值或确定其不存在于数组中。
首先,我们初始化两个指针left
和right
,分别指向数组的首尾元素。这里我们使用arr.size() - 1
来获取数组的最后一个元素的索引,因为arr
是一个vector
,我们可以利用vector
的size()
成员函数来动态获取数组大小。
int left = 0, right = arr.size() -1;
接下来,我们进入循环,并在每次循环中计算中间位置mid
。这里采用(left + right) >> 1的方式来计算mid.
int mid = left + right >> 1;
然后,我们比较arr[mid]
与关键字21的大小关系。如果arr[mid]
等于21,说明找到了目标值,我们输出其位置并退出循环。如果arr[mid]
大于21,说明目标值应该在mid
的左侧,因此我们将right
更新为mid - 1
。如果arr[mid]
小于21,说明目标值应该在mid
的右侧,因此我们将left
更新为mid + 1
。
while (left < right) {
int mid = left + right >> 1;
if (arr[mid] == num) {
cout << mid << endl;
return 0;
}else if (arr[mid] > num) {
right = mid - 1;
}
else {
left = mid + 1;
}
}
循环继续进行,直到left
大于right,跳出循环。
三、完整代码
#include<bits/stdc++.h>
using namespace std;
vector<int> arr = { 5, 13, 19, 21, 37, 56, 64, 76, 80, 88, 92 };//vector容器
int main() {
int left = 0, right = arr.size() - 1;
int num;
cout << "请输入给定关键字:";
cin >> num;
while (left < right) {
int mid = left + right >> 1;
if (arr[mid] == num) {
cout << mid << endl;
return 0;
}else if (arr[mid] > num) {
right = mid - 1;
}
else {
left = mid + 1;
}
}
return 0;
代码解释:这里使用了位右移操作 >>
来计算中间位置。left + right >> 1
相当于 (left + right) / 2。
四、总结
二分查找利用了线性表中元素的有序性,每经过一次比较就把线性表中的查找范围缩小一半,所以对于一次查找,无论成功还是失败,二分查找需要比较的次数都不会超过,也就说明二分查找的平均查找长度为O(logN)。
因为作者本人也是刚刚接触算法,如有不对,希望大佬可以指出!!!
这里有更加详细的解释,如有不懂,可以继续参考:算法---二分算法-CSDN博客