2016級演算法第三次上機-A.水水的二分查詢
阿新 • • 發佈:2018-12-09
借用著道題來複習一下 二分查詢
說起二分查詢 有幾個點是要重視的
1.最簡單的二分查詢
2.上下界二分查詢的實現
3.c++ STL 二分查詢三兄弟的使用
最簡單的二分查詢
1 #include <iostream> 2 #include <algorithm> 3 #include <cstring> 4 5 using namespace std; 6 const int maxlen=1e6 + 10; 7 int ar[maxlen]; 8 int BinarySearch(int left,int right,intvalue); 9 10 int main(){ 11 int n,t,x,i,j; 12 while(~scanf("%d",&n)){ 13 for(i=1;i<=n;i++) 14 scanf("%d",&ar[i]); 15 scanf("%d",&t); 16 while(t--){ 17 scanf("%d",&x); 18 printf("%d ",BinarySearch(1,n,x)); 19 }20 printf("\n"); 21 } 22 23 return 0; 24 } 25 int BinarySearch(int left,int right,int value){ 26 int middle=(left + right)/2; 27 while(left <= right){ 28 middle=(left+right)/2; 29 if(ar[middle] == value) 30 return middle; 31 else if(ar[middle] < value)32 left=middle+1; 33 else right=middle-1; 34 } 35 return -1; 36 }
上下界二分查詢:其實自己手寫上下界二分查詢其實也不難。上下界其實就是當你找到一個值無法直接確定這個值是否就是最小或者最大的值,這個時候我們最好的辦法就是先記錄好這個值,當之後如果有更適合的值就覆蓋,沒有就統一在最後面返回值。上下界二分查詢是一定可以返回值。
下面貼一個自己手寫過的下界二分查詢程式碼,其核心演算法是無論是上界還是下界二分查詢,都會出現多個符合值的情況,那我們每次遇到符合條件的值的時候,我們可以想辦法去縮小範圍更新,如果更新失敗,那麼最後直接返回即可。
#include <iostream> #include <algorithm> #include <cstring> using namespace std; const int maxlen=250000 + 10; int ar[maxlen]; int BinarySearch(int left,int right,int value); int main(){ int n,t,x,i,j,ans; while(~scanf("%d %d",&n,&t)){ for(i=1;i<=n;i++) scanf("%d",&ar[i]); while(t--){ scanf("%d",&x); ans=BinarySearch(1,n,x); if(ans == -1) printf("error\n"); else printf("%d\n",ans); } } return 0; } //下界二分查詢 //lowbound int BinarySearch(int left,int right,int value){ int middle=(left + right)/2; int pos=-1; while(left <= right){ middle=(left+right)/2; if(ar[middle]>value) right=middle-1; else if(ar[middle] == value){ pos=middle; right=middle-1; } else left=middle+1; } return pos; }
其實在c++ STL的庫函式裡有三個函式來幫助我們實現二分相關的查詢。
這三個函式的標頭檔案是<algorithm>
binary_search 查詢某個元素是否出現
函式模板:binary_search(arr[],arr[]+size , indx)
lower_bound:查詢第一個大於或等於某個元素的位置
upper_bound:查詢第一個大於某個元素的位置
其實這三個函式預設要求給定的陣列arr是非遞減的,當然如果OJ測試是給定的非遞增的,那我們可以在讀入的時候做點手腳。
在比較特殊的情況下,例如如果陣列中所有的數都小於index那麼這兩個函式的返回值均是last(陣列索引已經越界)
下面給定用STL二分過題的例子:
#include <iostream> #include <algorithm> #include <cstring> using namespace std; const int maxlen=250000 + 10; int ar[maxlen]; int main(){ int n,t,x,i,j,ans,flag; while(~scanf("%d %d",&n,&t)){ for(i=0;i<n;i++) scanf("%d",&ar[i]); while(t--){ scanf("%d",&x); if(binary_search(ar,ar+n,x) == false) printf("error\n"); else printf("%ld\n",lower_bound(ar,ar+n,x) - ar + 1); } } return 0; }
值的關注是這三個STL函式的返回值
binary_search()的返回值是bool型別的 即false or true
lower_bound() 和upper_bound()的返回值是指標型別的,所以如果要求解下標,需要與陣列的首地址進行運算。