C++STL標準庫學習筆記(二)二分查詢
二、STL中的二分查詢演算法
1.binary_search
2.lower_bound
3.upper_bound
記得#include<algorithm>!
前言:
在這個筆記中,我把大多數程式碼都加了註釋,我的一些想法和註解用藍色字型標記了出來,重點和需要關注的地方用紅色字型標記了出來。
1.1用binary_search進行二分查詢(用法一)
在從小到大排好序的基本型別陣列上進行二分查詢
binary_search(陣列名+n1, 陣列名+n2,值);
n1和n2都是int型別表示式,可以包含變數
如果n1=0,則 + n1可以不寫(這幾點和前面sort一樣)
查詢區間為下標範圍為[n1,n2)的元素,下標為n2的元素不在查詢區間內,在該區間內查詢“等於”值的元素,返回值為true(找 到)或false(沒找到)。(返回值不是位置哦)
等於的含義:a等於b <=> a<b和b<a都不成立。
不是a==b!
1.2用binary_search進行二分查詢(用法二)
在用自定義排序規則排好序的、元素為任意的T型別的陣列中進行二分查詢。
binary_search(陣列名+n1, 陣列名+n2, 值, 排序規則結構名());
n1和n2都是int型別表示式,可以包含變數
如果n1=0,則 + n1可以不寫
查詢區間為下標範圍為[n1,n2)的元素,下標為n2的元素不在查詢區間內,在該區間內查詢“等於”值的元素,返回值為true(找 到)或false(沒找到)。
查詢時的排序規則,必須和排序時的規則一致!
也不是說排序規則不一樣就一定找不到,有可能找到,但是找到的結果並沒有意義,說不定就是運氣好找到了。
等於的含義:a等於b <=> a<b和b<a都不成立。
樣例:
1 struct Rule//按個位數從小到大排 2 { 3 bool operator()(const int & a1, const int & a2)const{ 4 return a1%10 < a2%10; 5 } 6 }; 7 void Print(int a[],int size) 8 { 9 for樣例(int i = 0; i < size; i++) 10 { 11 cout<<a[i]<<","; 12 } 13 cout<<endl; 14 } 15 16 int main(int argc, char const *argv[]) 17 { 18 int a[] = {12,45,3,98,21,7}; 19 sort(a,a+sizeof(a)/sizeof(int));//從小到大排序 20 Print(a,sizeof(a)/sizeof(int));//結果:3,7,12,21,45,98, 21 cout<<"result:"<<binary_search(a,a+6,12)<<endl;//結果:1 22 cout<<"result:"<<binary_search(a,a+6,77)<<endl;//結果:0 23 sort(a,a+6,Rule()); 24 Print(a,6);//結果: 25 cout<<"result:"<<binary_search(a,a+6,7)<<endl;//結果:0//其實能找到結果,但是這是沒意義的,運氣好找到罷了。 26 cout<<"result:"<<binary_search(a,a+6,8,Rule())<<endl;//結果:1 27 //這個結果是1,因為'='的含義是a在b前面和b在a前面都不成立,不是“==”!這裡其實找到的是98。 28 return 0; 29 }
2.1用lower_bound二分查詢下界(用法一)
在對元素型別為T的從小到大排好序的基本型別的陣列中進行查詢
T * lower_bound(陣列名+n1, 陣列名+n2, 值);
返回一個指標 T * p;
*p 是查詢區間裡下標最小的,大於等於值的元素。如果找不到,p指向下標為n2的元素。(反正n2不在查詢區間內,要是要寫判斷可以用這個作為依據)
2.2用lower_bound二分查詢下界(用法二)
在元素為任意的T型別、按照自定義排序規則排好序的陣列中進行查詢
T * lower_bound(陣列名+n1, 陣列名+n2, 值, 排序規則名());
返回一個指標 T * p;
*p是查詢區間裡下標最小的,按自定義排序規則,可以排在“值”後面的元素。如果找不到,p指向下標為n2的元素。
3.1用upper_bound二分查詢上界(用法一)
在對元素型別為T的從小到大排好序的基本型別的陣列中進行查詢
T * upper_bound(陣列名+n1, 陣列名+n2, 值);
返回一個指標 T * p;
*p 是查詢區間裡下標最小的,大於值的元素。如果找不到,p指向下標為n2的元素。(這裡是大於,不要和前面弄混了)
3.1用upper_bound二分查詢上界(用法二)
在元素為任意的T型別、按照自定義排序規則排好序的陣列中進行查詢
T * upper_bound(陣列名+n1, 陣列名+n2, 值, 排序規則名());
返回一個指標 T * p;
*p是查詢區間裡下標最小的,按自定義排序規則,必須排在“值”後面的元素。如果找不到,p指向下標為n2的元素。(這裡是必須排在值後面的元素,相對來說,lower_bound是可以排在值後面,有可能等於,但是這個就不可能等於了,詳情可以看樣例)
樣例:(這個樣例挺全,各種情況都有)
1 //lower_bound是找到的下標最小的,按排序規則,大於等於值的元素 2 //upper_bound是找到的下標最小的,按排序規則,必須排在值後面的元素 3 //兩個都是找不到就指向下標為n2的元素 4 struct Rule//按個位數從小到大排 5 { 6 bool operator()(const int & a1, const int & a2)const{ 7 return a1%10 < a2%10; 8 } 9 }; 10 void Print(int a[],int size) 11 { 12 for (int i = 0; i < size; i++) 13 { 14 cout<<a[i]<<","; 15 } 16 cout<<endl; 17 } 18 19 int main(int argc, char const *argv[]) 20 { 21 int a[NUM] = {12,5,3,5,98,21,7}; 22 sort(a,a+sizeof(a)/sizeof(int));//從小到大排序 23 Print(a,sizeof(a)/sizeof(int));//結果:3,5,5,7,12,21,98 24 int *p = lower_bound(a,a+NUM,5); 25 cout<<*p<<","<<p-a<<endl;//結果:5,1 26 p = upper_bound(a,a+NUM,5); 27 cout<<*p<<endl;//結果:7 28 cout<<*upper_bound(a,a+NUM,13)<<endl;//結果:21 29 //這裡可以看見不用查詢陣列記憶體在的元素也有返回值,當然,這裡用binary_search()就會返回false了 30 sort(a,a+NUM,Rule()); 31 Print(a,NUM);//結果:21,12,3,5,5,7,98, 32 cout<<* lower_bound(a,a+NUM,16,Rule())<<endl;//結果:7 33 cout<< lower_bound(a,a+NUM,25,Rule())-a<<endl;//結果:3//這裡結果是下標 34 cout<< upper_bound(a,a+NUM,18,Rule())-a<<endl;//結果:7//這裡結果也是下標,畢竟沒找到 35 if (upper_bound(a,a+NUM,18,Rule())==a+NUM) 36 { 37 cout<<"not found"<<endl;//not found,這裡是一個例子,如何判斷沒有找到 38 } 39 cout<<*upper_bound(a,a+NUM,5,Rule())<<endl;//結果:7 40 cout<<*upper_bound(a,a+NUM,4,Rule())<<endl;//結果:5 41 return 0; 42 }樣例
後記:
又學完一節,不得不說STL標準庫確實好用,但是平常記不記得用就是個難題了,很多時候我們的思維都固化了,勇敢的嘗試新事物有助於我們能力的提升(指想得到用剛學的STL標準庫),而在這跳出舒適區的過程中,我們也會收穫成長的快樂,總之感謝大家讀到這裡,我run了,祝大家健康快樂吉祥如意恭喜發財學業有成早生貴子,以及頭髮茂密,下篇部落格再見拜拜。