Effective_STL 學習筆記(四十五) 注意 count、find、binary_search、lower_bound、upper_bound 和 equal_range 的區別
如果區間有序,可以使用對數時間的演算法,binary_search、lower_bound、upper_bound 和 equal_range
如果迭代器沒有劃分一個有序區間,只能用線性時間的演算法 count、count_if、find 和 find_if
cout 回答: 是否存在這個值,如果有,那麼存在幾分拷貝?
find 回答: 是否存在,如果有,那麼它在哪?
count 返回零或一個正數,所以把非零轉換為 true 而把零轉化為 false
1 if( count(lw.begin(), lw.end(), w) ) //檢查是否有w在lw中 2 . . .
使用 find 的演算法可以在搜尋到就停止,不必繼續搜尋
1 if( find( lw.begin(), lw.end(), w ) != lw.end() ) 2 . . . // 找到了 3 else 4 . . . // 沒找到
想獲得區間中的第一個等於該值的物件,就得使用 find:
1 list<Widget>::iterator i = find( lw.begin(), lw.end(), w ); 2 if( i != lw.end() )3 . . . // 找到了,i 指向第一個 4 else 5 . . . // 沒有找到
有序區間搜尋演算法是線性時間的 binary_search、lower_bound、upper_bound 和 equal_range 是對數時間的,從無序區間遷移到有序區間導致另一個遷移:從使用相等來判斷兩個值是否相同到使用等價來判斷。
binary_searh 回答: 它在嗎?它的回答只能是是或者不是
1 if( binary_search( lw.begin(), lw.end(), w ) ) 2 . . . // w 在 lw 中3 else 4 . . . // w 不在 lw 中
如果要回答: 它在嗎,如果是,那麼在哪裡? 你就需要 equal_range,但可能想要 lower_bound
lower_bound 回答: 它在嗎?如果是,第一個拷貝在哪?如果不是,它將在哪裡?
lower_bound 要檢測返回值是否等於 end 迭代器,還要檢測標識物件是都為找的值
1 vector<Widget>::iterator i = lower_bound( vw.begin(), vw.end(), w ); 2 if( i != vw.end() && *i == w ) // 這有一個 bug 3 . . . 4 else 5 . . .
大多數情況能通過,bug 在於 *i == w 這是一個相等測試,而 lower_bound 用的是等價測試
equal_range 返回一對迭代器,第一個等於 lower_bound 返回的迭代器,第二個等於 upper_bound 返回的迭代器。因此,equal_range 返回了一對劃分出了和你要搜尋的值的等價的區間的迭代器。
1 vector<Widget> vw; 2 . . . 3 sort( vw.begin(), vw.end() ); 4 typedef vector<Widget>::iterator VWIter; 5 typedef pair<VWIter, VWIter> VWIterPair; 6 VWIterPair p = equal_range( vw.begin(), vw.end(), w ); 7 if( p.first != p.second ) 8 . . . // 找到了,p.first 指向第一個,p.second 指向第二個 9 else 10 . . . // 沒找到 p.first 和 p.second 都指向搜尋值的插入位置
equal_range 返回的東西是兩個迭代器,對他們作 distance 就等於區間中物件的數目,也就是等價於要尋找的值的物件。equal_range 不光完成了搜尋有序區間的任務,而且完成了計數(distance())
1 cout<<"There are"<< distance(p.first, p.second) <<"elements in vw";
對於標準關聯容器(set、multiset、map 和 multimap)使用它們成員函式代替同名演算法,沒有 binary_search 對應的成員函式,對於 set 或者 map 使用 count 的慣用法,對於 multiset 和 multimap 使用 find 比 count 好。