二分查找算法

来源:互联网 发布:atheros linux驱动 编辑:程序博客网 时间:2024/06/06 03:15
二分查找算法前提有2个:1.必须采用顺序存储结构,2.必须按关键字有序排列。时间复杂度为O(logn)

        算法主要思想:将n个元素分成两半,取a[n/2]与欲查找的x作比较,如果x=a[n/2]则找到x,算法终止。如果x<a[n/2],则我们只要在数组a的左半部继续搜索x(这里假设数组元素呈升序排列)。如果x>a[n/2],则我们只要在数组a的右半部继续搜索x。

如果考虑到时间效率,代码中最好是将相等的情况放在最后一个判断中,因为相等的概率比大于和小于的概率要小很多,如果放在第一个判断会损耗一部分时间。

        二分查找法容易存在一个临界值的BUG。以下是2种正确的算法,分别是左闭右闭、左闭右开。n为数组元素个数,即最大下标为n-1,两个算法有3个不同点,分别是high的初始值、while条件、high的赋值:

非递归版本:

[cpp] view plaincopyprint?
  1. #include<iostream>   
  2. using namespace std;  
  3. int BinSearch(int arr[],int n,int data)  
  4. {  
  5.     int low=0,high=n-1;//左闭右闭区间 ,high为n-1   
  6.     while(low<=high)//含等号(左闭右闭)  
  7.     {  
  8.         int mid=(low+high)/2;  
  9.         if(arr[mid]==data)  
  10.             return mid;  
  11.         else if(arr[mid]>data)  
  12.             high=mid-1; //mid-1(左闭右闭)   
  13.         else  
  14.             low=mid+1;  
  15.     }  
  16.     return -1;  
  17. }  
  18. int BinSearch2(int arr[],int n,int data)  
  19. {  
  20.     int low=0,high=n;//左闭右开区间 ,high为n   
  21.     while(low<high)//不含等号(左闭右开)  
  22.     {  
  23.         int mid=(low+high)/2;  
  24.         if(arr[mid]==data)  
  25.             return mid;  
  26.         else if(arr[mid]>data)  
  27.             high=mid;//mid不减1(左闭右开)  
  28.         else  
  29.             low=mid+1;  
  30.     }  
  31.     return -1;  
  32. }  
  33. int main()  
  34. {  
  35.     int a[]={0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20};  
  36.     for(int i=0;i<22;i++)  
  37.         cout<<BinSearch(a,21,i)<<endl;  
  38.     return 0;  
  39. }  
#include<iostream>using namespace std;int BinSearch(int arr[],int n,int data){int low=0,high=n-1;//左闭右闭区间 ,high为n-1 while(low<=high)//含等号(左闭右闭){int mid=(low+high)/2;if(arr[mid]==data)return mid;else if(arr[mid]>data)high=mid-1;//mid-1(左闭右闭)elselow=mid+1;}return -1;}int BinSearch2(int arr[],int n,int data){int low=0,high=n;//左闭右开区间 ,high为n while(low<high)//不含等号(左闭右开){int mid=(low+high)/2;if(arr[mid]==data)return mid;else if(arr[mid]>data)high=mid;//mid不减1(左闭右开)elselow=mid+1;}return -1;}int main(){int a[]={0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20};for(int i=0;i<22;i++)cout<<BinSearch(a,21,i)<<endl;return 0;}

以下是典型的错误算法:

[cpp] view plaincopyprint?
  1. #include<iostream>   
  2. using namespace std;  
  3. int BinSearch3(int arr[],int n,int data)  
  4. {  
  5.     int low=0,high=n;//左闭右开区间 ,high为n   
  6.     while(low<high)//不含等号   
  7.     {  
  8.         int mid=(low+high)/2;  
  9.         if(arr[mid]==data)  
  10.             return mid;  
  11.         else if(arr[mid]>data)  
  12.             high=mid-1;//mid减1    
  13.         else  
  14.             low=mid+1;  
  15.     }  
  16.     return -1;  
  17. }  
  18. int main()  
  19. {  
  20.     int a[]={0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20};  
  21.     for(int i=0;i<22;i++)  
  22.         cout<<BinSearch3(a,21,i)<<endl;  
  23.     system("pause");  
  24.     return 0;  
  25. }  
#include<iostream>using namespace std;int BinSearch3(int arr[],int n,int data){int low=0,high=n;//左闭右开区间 ,high为n while(low<high)//不含等号 {int mid=(low+high)/2;if(arr[mid]==data)return mid;else if(arr[mid]>data)high=mid-1;//mid减1 elselow=mid+1;}return -1;}int main(){int a[]={0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20};for(int i=0;i<22;i++)cout<<BinSearch3(a,21,i)<<endl;system("pause");return 0;}

运行结果如下,此时很多存在的值查找不到:


非递归版本(正确):

[cpp] view plaincopyprint?
  1. #include<iostream>   
  2. using namespace std;  
  3. int BinSearch(int arr[],int low,int high,int data)  
  4. {//参数为最小最大下标,非递归参数为数组元素个数   
  5.     if(low<=high)//low和high相等时只含一个元素,此时仍需查找,故含等号  
  6.     {  
  7.         int mid=(low+high)/2;  
  8.         if(arr[mid]==data)  
  9.             return mid;  
  10.         else if(arr[mid]>data)  
  11.             return BinSearch(arr,low,mid-1,data);     
  12.         else  
  13.             return BinSearch(arr,mid+1,high,data);    
  14.     }  
  15.     else  
  16.         return -1;//查找不到  
  17. }  
  18. int main()  
  19. {  
  20.     int a[]={0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20};  
  21.     for(int i=0;i<22;i++)  
  22.         cout<<BinSearch(a,0,20,i)<<endl;  
  23.     system("pause");  
  24.     return 0;  
  25. }  
#include<iostream>using namespace std;int BinSearch(int arr[],int low,int high,int data){//参数为最小最大下标,非递归参数为数组元素个数if(low<=high)//low和high相等时只含一个元素,此时仍需查找,故含等号{int mid=(low+high)/2;if(arr[mid]==data)return mid;else if(arr[mid]>data)return BinSearch(arr,low,mid-1,data);elsereturn BinSearch(arr,mid+1,high,data);}elsereturn -1;//查找不到}int main(){int a[]={0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20};for(int i=0;i<22;i++)cout<<BinSearch(a,0,20,i)<<endl;system("pause");return 0;}


原创粉丝点击