当前位置:   article > 正文

C/C++分治算法(1)——二分查找_c++ 二分查找

c++ 二分查找

常见分治算法总结(1)二分查找

一篇文章,带你搞懂 二分查找 (注:代码语言的选择不应该限制了我们对算法的理解)

文章附有动图!一看就懂!

温馨提示:代码在文章末尾


二分查找又叫折半查找,顾名思义,指的是每次的查找范围折半。

优点:比较次数少、查找速度快、平均性能好。

缺点:要求待查找的数据已被整理为有序,换而言之,就是要求数组有序

主要功能:在一个已按非降序排序的序列Array中,查找是否存在一个元素key,如果存在,返回该元素的索引值,否则返回-1(c语言中数组的任何元素索引都不可能为-1,利用这点,使用-1表示不存在该元素)

 
实现原理:
1、确定有序序列的中位数Array[mid],并且将该中位数与key相比较。
2、如果Array[mid]>key,说明key可能在序列前半部分;否则Array[mid]<key,说明,key可能在序列后半部分;这种情况直接排除序列另外一部分(序列的一半)。如果碰巧Array[mid]=key;这时即可直接确定key索引值。

查找成功的情况

假设原始序列为array=[3, 12, 24, 31, 46, 48, 52, 66, 69, 79, 82],目标元素target=52。

1. 开始时,low=0,high=10,mid=(low + high) / 2 = 5。

比较中间元素和目标元素,48小于52。这说明若目标元素存在,则它必定在原序列的后半部分。让low=mid + 1 = 6而high不变,这样low和high就指向了原序列的后半部分。

2. 此时,low=6,high=10,mid=(low + high) / 2 = 8。

同样的,比较新的中间元素和目标元素,69大于52。这说明若目标元素存在,它必定在当前待查序列的前半部分。让high=mid - 1 = 7而low不变,这样low和high就指向当前待查序列的前半部分。

3. 此时,low=6,high=7,mid=(low + high) / 2 = 6。

比较新的中间元素和目标元素,52等于52。查找成功,返回该中间元素的索引6并退出算法。

 

查找不到的情况

假设原始序列为array=[5, 10, 22, 29, 43, 57, 58, 61, 73, 77, 81],目标元素target=70。

1. 开始时,low=0,high=10,mid=(low + high) / 2 = 5;

 比较中间元素和目标元素,57小于70。这说明若目标元素存在,那么它一定在原序列的后半部分。让low=mid + 1 = 6而high不变,这样low和high就指向原序列的后半部分。

2. 此时,low=6,high=10,mid=(low + high) / 2 = 8;

比较新的中间元素和目标元素,73大于70。这说明若目标元素存在,那么它一定在当前待查序列的前半部分。让high=mid - 1 = 7而low不变,这样low和high就指向当前待查序列的前半部分。

3. 此时,low=6,high=7,mid=(low + high) / 2 = 6;

比较新的中间元素和目标元素,58小于70。这说明若目标元素存在,那么它一定在当前待查序列的后半部分。让low=mid + 1 = 7而high不变,这样low和high就指向当前待查序列的后半部分。

4. 此时,low=7,high=7,mid=(low + high) / 2 = 7;

比较新的中间元素和目标元素,61小于70。这说明若目标元素存在,那么它一定在当前待查序列的后半部分。让low=mid + 1 = 8而high不变。

 5. 此时,low=8,high=7,low大于high说明待查序列已为空,也就说明查找不到目标元素。此时,返回-1并退出算法,表示查找不成功;

我们通过动态图来对比一下二分查找和顺序查找的性能,明显看出二分查找速度之快

在这里插入图片描述

非递归代码实现

  1. #include<iostream>
  2. using namespace std;
  3. int binarySearch(int arr[],int n,int value){
  4. int low = 0;
  5. int high = n-1;
  6. //这里我们默认从小到大排序
  7. while(low <= high){
  8. int mid = low + ((high - low) /2);//也可以是mid=(low+high)/2
  9. if(arr[mid]==value) return mid;
  10. else if(arr[mid] > value){
  11. //中间比value大,往左边(较小)的方向找
  12. high = mid - 1;
  13. }else if(arr[mid] < value){
  14. //中间比value小,往右边(较大)的方向找
  15. low = mid + 1;
  16. }
  17. }
  18. return -1;
  19. }
  20. int main(){
  21. int i,value=26;
  22. int arr[10]={1,5,7,13,17,23,26,36,48,88};
  23. printf("原始数组:\n");
  24. for(i=0;i<10;i++) printf("%d ",arr[i]);
  25. printf("\n待查找的数据:%d\n",value);
  26. int ans = binarySearch(arr,10,value);
  27. if(ans!=-1){
  28. printf("%d在数组的下标为:%d\n",value,ans);
  29. }else{
  30. printf("没有找到%d\n",value);
  31. }
  32. return 0;
  33. }

递归代码实现

  1. #include<iostream>
  2. using namespace std;
  3. int binarySearch(int arr[],int low,int high,int value){
  4. //这里我们默认从小到大排序
  5. if(low > high) return -1;
  6. //找中间下标
  7. int mid = low + ((high - low) /2);//也可以是mid=(low+high)/2
  8. if(arr[mid]==value) return mid;
  9. else if(arr[mid] > value){
  10. //中间比value大,往左边(较小)的方向找
  11. binarySearch(arr,low,mid-1,value);
  12. }else if(arr[mid] < value){
  13. //中间比value小,往右边(较大)的方向找
  14. binarySearch(arr,mid+1,high,value);
  15. }
  16. }
  17. int main(){
  18. int i,value=26;
  19. int arr[10]={1,5,7,13,17,23,26,36,48,88};
  20. printf("原始数组:\n");
  21. for(i=0;i<10;i++) printf("%d ",arr[i]);
  22. printf("\n待查找的数据:%d\n",value);
  23. int ans = binarySearch(arr,0,10-1,value);
  24. if(ans!=-1){
  25. printf("%d在数组的下标为:%d\n",value,ans);
  26. }else{
  27. printf("没有找到%d\n",value);
  28. }
  29. return 0;
  30. }

声明:本文内容由网友自发贡献,转载请注明出处:【wpsshop博客】
推荐阅读
相关标签
  

闽ICP备14008679号