之前用這兩個函數的時候,簡單看了幾句別人的博客,記住了大概,用的時候每用一次就弄混一次,至關難受,今天對照着這兩個函數的源碼和本身的嘗試發現:其實這兩個函數只能用於 「升序」 序列。c++
爲何還要加個引號呢?由於比較規則能夠自定義,若是你非要把比較規則定義成 5 比 3 小,那麼 降序序列也是能夠用的,不然不能夠,直接看下例子(這是升序序列的 ):
數組
#include<bits/stdc++.h> using namespace std; int main() { int a[] = {1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4}; cout << (lower_bound(a, a + 12, 4) - a) << endl; //輸出 9 cout << (upper_bound(a, a + 12, 4) - a) << endl; //輸出 12 cout << (lower_bound(a, a + 12, 1) - a) << endl; //輸出 0 cout << (upper_bound(a, a + 12, 1) - a) << endl; //輸出 3 cout << (lower_bound(a, a + 12, 3) - a) << endl; //輸出 6 cout << (upper_bound(a, a + 12, 3) - a) << endl; //輸出 9 cout << (lower_bound(a, a + 12, 5) - a) << endl; //輸出 12 cout << (upper_bound(a, a + 12, 5) - a) << endl; //輸出 12 cout << (lower_bound(a, a + 12, 0) - a) << endl; //輸出 0 cout << (upper_bound(a, a + 12, 0) - a) << endl; //輸出 0 return 0; }
不出所料,在對 4 進行 lower_bound 時,輸出結果是 9,由於在升序序列中 lower_bound 返回第一個大於等於 參數val 的 序列值的迭代器,這裏 val 爲 4,lower_bound 進行二分查找,找到第一個 4 時符合條件因此返回(確切的說當步長減到 0 時,欲返回的這個迭代器會停在第一個 4 那裏),而後減去首迭代器 a,就是兩個迭代器的距離了(在這裏也就是數組中下標),第一個 4 的下標是 9。在對 4 進行 upper_bound 時,輸出結果是 12,由於在升序序列中 upper_bound 返回第一個大於 參數val 的 序列值的迭代器,不幸的是這個序列裏找不到大於 4 的值,因此迭代器走到盡頭也沒有找到,因而返回了一個尾迭代器(在這裏是數組越界後的那一個元素的指針),它在數組中下標爲 12 。同理能夠對剩下的那幾個分析。函數
那麼若是是降序序列呢?若是是降序序列,這個函數仍然覺得你這個序列是升序的,咱們以{4,4,4,3,3,3,2,2,2,1,1,1}做爲例子,試驗一下。
spa
#include<bits/stdc++.h> using namespace std; int main() { int a[] = {4, 4, 4, 3, 3, 3, 2, 2, 2, 1, 1, 1}; cout << (lower_bound(a, a + 12, 4) - a) << endl; // 輸出 12 cout << (upper_bound(a, a + 12, 4) - a) << endl; // 輸出 12 cout << (lower_bound(a, a + 12, 1) - a) << endl; // 輸出 0 cout << (upper_bound(a, a + 12, 1) - a) << endl; // 輸出 0 cout << (lower_bound(a, a + 12, 3) - a) << endl; // 輸出 12 cout << (upper_bound(a, a + 12, 3) - a) << endl; // 輸出 12 return 0; }
不難發現,這兩個函數的輸出結果都很無厘頭,不是指望的結果,那麼爲何會這樣呢?剛纔說了,這個函數仍然覺得你這個序列是升序的,以這句爲例 lower_bound(a, a + 12, 4) ,由於是二分查找,第一步從中間開始,取中間值 a[(0+12)/2] = a[6] = 2 ,比 4 小,可是他想要找到第一個大於等於 4 的,因此繼續向更大的值靠近,向哪邊靠近呢,右邊,由於他覺得你這是升序的,因此取右半部分中間值 a[(7+12)/2] = a[9] = 1,比 4 小,因此繼續向更大的值靠近,取右半部分中間值 a[(10+12)/2] = a[11] = 1,比 4 小,因此繼續向更大的值靠近,取右半部分中間值 a[(12+12)/2] = a[12],到這不用取了,到頭了,該返回了,因此最終返回了尾迭代器。.net
對照一下它的一個可能的實現源碼,或許有助於理解。指針
這個 iterator_traits<ForwardIterator>::difference_type 其實就是個 int 類型,只是另起了一羣其餘名字,distance 函數是計算兩個迭代器之間距離,advance 函數是將參數1(迭代器類型)前進 step 步,剩下的就沒有什麼不認識的東西了。code
template <class ForwardIterator, class T> ForwardIterator lower_bound (ForwardIterator first, ForwardIterator last, const T& val) { ForwardIterator it; iterator_traits<ForwardIterator>::difference_type count, step; count = distance(first, last); while(count > 0) { it = first; step = count / 2; advance(it, step); if (*it < val) { // or: if (comp(*it,val)), for version (2) first = ++it; count -= step + 1; } else count = step; } return first; }
轉載自:
---------------------
做者:錦夏挽秋
來源:CSDN
原文:https://blog.csdn.net/qq1337715208/article/details/81072709blog