在开始接触二分查找之前,先来了解一下最常见也是最简单的线性查找。
在一个数组中存在 { 4 , 1 , 5 , 2 , 3 , 6 , 9 , 10 , 7 , 8 } \begin{array}{c}\left \{ 4,1,5,2,3,6,9,10,7,8 \right \} \end{array} {4,1,5,2,3,6,9,10,7,8}数据,当我们需要查找 6 6 6这个数字的时候,只需要遍历整个数组即可,此方法的时间复杂度为 O ( n ) O(n) O(n)。
#include
using namespace std;
int main(){
int num[10]={4,1,5,2,3,6,9,10,7,8};
for(int i=0;i<10;i++){
if(num[i]==6){
cout<<"successful";
break;
}
}
return 0;
}
由此可见,在数据量较小的时候,采用线性查找的效果更加。当在大量数据的情况下,线性查找的效率就会显得很低。
二分查找也称为折半查找,原理是通过 n n n次的对比,将查找范围缩小到原本的 1 2 n \begin{array}{c}\frac{1}{2^{n}} \end{array} 2n1,从而达到提升搜索效率的目的。
根据以上的性质,我们需要将数组内的数据进行排序为 { 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10 } \begin{array}{c}\left \{ 1,2,3,4,5,6,7,8,9,10 \right \} \end{array} {1,2,3,4,5,6,7,8,9,10},才能进行下一步的二分查找。
排序方法见以往博客:排序算法:基础入门篇
此时的取值范围为 [ 1 , 10 ] [1,10] [1,10],我们将数组进行第一次二分,可知其中间数为 5 5 5,由于目标数字大于 5 5 5,此时我们的查找范围缩小到 [ 6 , 10 ] [6,10] [6,10],接着继续下分,最终找到目标数字 6 6 6。因此二分查找的时间复杂度为 O ( l o g 2 n ) O(log_2n) O(log2n)。
#include
using namespace std;
int binarySearch(int arr[], int l, int r, int x){
while(l <= r){
int mid = l + (r-l)/2;
if(arr[mid] == x)
return mid;
if(arr[mid] < x)
l = mid + 1;
else
r = mid - 1;
}
return -1;
}
int main(){
int arr[] = {1,2,3,4,5,6,7,8,9,10};
int n = sizeof(arr) / sizeof(arr[0]);
int x = 6;
int result = binarySearch(arr, 0, n-1, x);
if(result == -1)
cout << "目标不存在" << endl;
else
cout << "目标数为: " << result << endl;
return 0;
}
以上的查找方法可以成为二叉树的建立方法。首先我们取出中间数 5 5 5,根据二叉树的性质,比根节点小的放在左子树,比根节点大的放在右子树。由此可以写出完整的二叉树。
当我们建立好这个树之后,在今后的查找中,我们仅需要通过二叉树的性质就能轻松找到对应的节点。