1. 程式人生 > 其它 >C++STL標準庫學習筆記(二)二分查詢

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了,祝大家健康快樂吉祥如意恭喜發財學業有成早生貴子,以及頭髮茂密,下篇部落格再見拜拜。