如果区间有序,可以使用对数时间的算法,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 好。