• 转:正确区分不同的查找算法count,find,binary_search,lower_bound,upper_bound,equal_range


    首先可供查找的算法大致有count,find,binary_search,lower_bound,upper_bound,equal_range。带有判别式的如count_if,find_if或者binary_search的派别式版本,其用法大致相同,不影响选择,所以不作考虑。
    注意这些查找算法需要序列式容器,或者数组。关联容器有相应的同名成员函数except binary_search

    首先,选择查找算法时,区间是否排序是一个至关重要的因素
    可以按是否需要排序区间分为两组:
    A. count,find
    B. binary_search,lower_bound,upper_bound,equal_range
    A组不需排序区间, B组需要排序区间。
    当一个区间被排序,优先选择B组,因为他们提供对数时间的效率。而A则是线性时间

    另外A组B组所依赖的查找判断法则不同,A使用相等性法则(查找对象需要定义operator==), B使用等价性法则(查找对象需要定义operator<,必须在相等时返回false)。 

    A组的区别
    count:计算对象区间中的数目。
    find:返回第一个对象的位置。
    查找成功的话,find会立即返回,count不会立即返回(直到查找完整个区间),此时find效率较高。
    因此除非是要计算对象的数目,否则不考虑count。

    B组的区别 {1,3,4,5,6}
    binary_search:判断是否存在某个对象
    lower_range: 返回>=对象的第一个位置,lower_bound(2)=3, lower_bound(3)=3
    目标对象存在即为目标对象的位置,不存在则为后一个位置.
    upper_bound: 返回>对象的第一个位置, upper_bound(2)=3,upper_bound(3)=4
    无论是否存在都为后一个位置.
    equal_range: 返回由lower_bound和upper_bound返回值构成的pair,也就是所有等价元素区间。
    equal_range有两个需要注意的地方:
    1. 如果返回的两个迭代器相同,说明查找区间为空,没有这样的值
    2. 返回迭代器间的距离与迭代器中对象数目是相等的,对于排序区间,他完成了count和find的双重任务

    详细的建议可参考EffectiveSTL-169
    下面针对排序区间给出一些例子
    1. 查找元素及数目
    vector<Widget> vw; 
    ...
    typedef vector<Widget>::iterator VWIter;
    typedef pair<VWIter, VWIter> VWIterPair;
    VWIterPair p = equal_range(vw.begin(), vw.end(), w);
    const int count = distance(p.first, p.second);
    for(VWIter it = p.first; it!=p.second; ++it)
    { ... }

    // 在这里将抛弃传统的查找算法lower_bound(),因为其做法稍嫌麻烦
    // it = lower_bound(..);
    // if (it != v.end() && !(w < it)) //存在

    2. 删除ageLimit前的对象
    Timestamp ageLimit;
    ...
    v.erase(v.begin(), lower_bound(v.begin(), v.end(), ageLimit));

    3. 删除非ageLimit后的对象
    v.erase(v.begin(), upper_bound(v.begin(), v.end(), ageLimit));

    4. list按序插入(通常不需这么做,只需在整个插入之后排一次需即可)
    list<Person> lp; struct PersonSortPred{...}//按等价排序
    ...
    lp.insert(upper_bound(lp.begin(), lp.end(), newPerson, PersonSortPred()), newPerson);

    一些例外:对关联容器
    如果是set或map,只需要知道是否存在某值,使用count()代替find().因为set中无重复值
    multiset或multimap,则用find();
    要对关联容器记数,使用count(),因为可能比先equal_range(),在distance()由更快的速度。

  • 相关阅读:
    快速幂
    Oracle悲观锁和乐观锁
    UTL_RAW的问题?
    Linux操作系统下关于Top命令的参数详解
    存储过程与函数
    网站前端优化一些小经验
    Java获取各种常用时间方法2
    Pro CSS Techniques 读书笔记(六)
    Java获取各种常用时间方法
    Oracle专用服务器与共享服务器的区别
  • 原文地址:https://www.cnblogs.com/youxin/p/2568960.html
Copyright © 2020-2023  润新知