effective stl 第45条:正确区分count/find/binary_search/lower_bound/upper_bound/equal_range

来源:互联网 发布:安卓网络嗅探器怎么用 编辑:程序博客网 时间:2024/04/30 00:57

查找信息:binary_search/lower_bound/upper_bound/equal_range/count/count_if/find/find_if

如果迭代器区间的数据是有序的:建议使用binary_search/lower_bound/upper_bound/equal_range(使用等价性搜索)
如果迭代器区间的数据是无序的:建议使用count/count_if/find/find_if(使用相等性搜索)

=================count和find==================
count回答的问题是:区间中是否存在某个特定的值,如果存在,有多少个拷贝
find回答的问题是:区间中是否存在某个特定的值,如果存在话,它在哪里

void CountVSFind(){    //要求:问list中是否存在10    list<int> lInt;    int special = 10;    //dosomething    if (count(lInt.begin(), lInt.end(), special))    {        //if num>0     }    else    {        //if notfound    }    //The next is find    if (find(lInt.begin(), lInt.end(), special) != lInt.end())    {        //find    }    else    {        //notfound    }    //就我们要求来看,这两种都能实现要求的功能,但是就效率来看,find更好    //因为我们不在意几个,而是是否存在,并且find找到第一个之后就返回了}
#include<iostream>#include<list>#include<algorithm>#include<vector>#include<set>using namespace std;template<typename Con>void Print(Con v){    Con::iterator it = v.begin();    for (; it != v.end(); ++it)    {        cout << *it << endl;    }}void CountVSFind(){    //要求:问list中是否存在10    list<int> lInt;    int special = 10;    //dosomething    if (count(lInt.begin(), lInt.end(), special))    {        //if num>0     }    else    {        //if notfound    }    //The next is find    if (find(lInt.begin(), lInt.end(), special) != lInt.end())    {        //find    }    else    {        //notfound    }    //就我们要求来看,这两种都能实现要求的功能,但是就效率来看,find更好    //因为我们不在意几个,而是是否存在,并且find找到第一个之后就返回了}//==========下边是排序区间使用搜索函数的示例=========================void binarySearchFunction(vector<int> v,int num){    //注意binary_search的返回值是bool型,即只告诉你是否存在    sort(v.begin(), v.end());    if (binary_search(v.begin(), v.end(), num))    {        //找到    }    else    {        //没找到    }}void lowerBoundFUnction(vector<int> v, int num){    //lower_bound回答的问题是:这个值存在于区间中么?如果存在,她的第一份    //拷贝在哪里?如果不存在,它应该往哪里插入    sort(v.begin(), v.end());    vector<int>::iterator it = lower_bound(v.begin(), v.end(), num);    if (it != v.end() && *it != num)    {        //注意,不能仅仅使用end迭代器来测试lower_bound的返回值        //相反必须测试返回值所指向的对象,从而判断该对象是否是你想要找的值        //确保i指向一个对象,并且该对象有正确的值;这里是一个错误        //找到了该值,it指向第一个具有该值的对象    }    else    {        //没有找到    }    //注意,其实上边的代码是有问题的    //因为if()中的条件其实是相等测试,而我们需要的是等价测试    //有一种更容易的方法,就是使用equal_range,请接着看下边的代码}void equalRangeFunction(vector<int> v, int num){    //equal_range返回一对迭代器,第一个等于lower_bound返回的迭代    //器,第二个等于upper_bound返回的(也就是,等价于要搜索值区间的末迭代器的下一个)    sort(v.begin(), v.end());    typedef vector<int>::iterator intIter;    typedef pair<intIter, intIter> intPair;    intPair p = equal_range(v.begin(), v.end(), num);    if (p.first != p.second)    {        //如果equal_range返回的是非空区间,找到了特定的值,p.first指向的是        //第一个与num等价的对象,p.second指向的是最后一个与Num等价对象的下一个对象    }    else    {        //如果没有找到特定值,p.first和p.second都指向num的插入位置    }    //equal_range返回的迭代器之间的距离与这个区间中对象的数目是相等的。    //因此,下边的代码将显示与num等价的代码一共有多少个    cout << "There are" << distance(p.first, p.second)        << "elements in v equal to num." << endl;}//下边的函数使lower_bound和upper_bound的用法举例void LowerExample(){    //现在假设vector<int>中是按照从小到大的顺序排列    vector<int> v;    for (int i = 0; i <=20; i++)    {        v.push_back(i);    }    //假设要删除那些>10的数字    v.erase(v.begin(), lower_bound(v.begin(), v.end(), 10));    Print<vector<int>>(v);}void UpperExample(){    //现在假设vector<int>中是按照从小到大的顺序排列    vector<int> v;    for (int i = 0; i <= 20; i++)    {        v.push_back(i);    }    //假设要删除那些>=10的数字    v.erase(v.begin(), upper_bound(v.begin(), v.end(), 10));    Print<vector<int>>(v);}class person{public:    person(){};    const string& name() const{ return thisname; };private:    string thisname;};struct PersonNameLess :    public binary_function<person, person, bool>{    bool operator()(const person& lhs, const person& rhs) const    {        return lhs.name() < rhs.name();    }};void ListUpperExample(){    list<person> lp;    lp.sort(PersonNameLess());//按照从小到大的顺序进行排列    person newPerson;    //dosomethind    //将newPerson插入到lp中排在最后一个newPerson之前或者与newPerson等价的对象之后    lp.insert(upper_bound(lp.begin(), lp.end(), newPerson, PersonNameLess()),newPerson);    //这段代码方便而且正确,但是并不意味着在list中使用upper_bound来找到插入的位置只需要    //对数的时间,不是这样的,在34条中解释过原因。因为我们操作了一个list,所以它只执行了对数次数    //的比较次数,但是查找仍需要线性的时间。}//但是对于标准的关联容器,情形就不同了,它们自带的成员函数比STL算法更加好void GuanlianContainExample(){    //凡是在前边的讨论中建议选择的算法count/find/equal_range/lower_bound/upper_bound    //的地方,针对关联容器,只需要选择同名的成员函数即可。只有binary_search是个例外,因为    //关联容器中不存在同名的函数    set<int> si;    //doSomethind,在set中插入数据    int num = 10;//待查找的数据    if (si.count(num))    {        //存在与num等价的值    }    else    {        //不存在与num等价的值    }    //要在multiset和multimap中测试一个值是否存在,用count就好了    //但是要是统计某个值的个数,用count就行}int main(){    UpperExample();}

相关表格

0 0
原创粉丝点击