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

查找信息: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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值