对于std :: pair的容器,std :: set :: equal_range

时间:2012-11-11 23:00:29

标签: c++ c++11

我试图找到包含int值i的所有范围[a,b],其中a&lt; = i&lt; = b。我正在使用set<std:pair<int,int>>作为范围集。

在下文中,在vector<int>上使用相等范围会产生开始,并且在范围结束时产生一个范围。

当我为set<pair<int,int>>执行相同操作时,结果将在范围结束时开始和结束,因此不包括包含该值的范围。

#include <set>
#include <iostream>
#include <algorithm>
using namespace std;

int main()
{
    int ia[] = {1,2,3,4,5,6,7,8,9,10};
    set<int> s1(begin(ia),end(ia));
    auto range1 = s1.equal_range(5);

    cout << *range1.first << " " << *range1.second << endl; //prints 5 6

    pair<int,int> p[] = {make_pair(1,10), 
                         make_pair(11,20),  
                         make_pair(21,30), 
                         make_pair(31,40)}; 
    set<pair<int,int>> s(begin(p), end(p));    

    auto range = s.equal_range(make_pair(12,12));

    cout << range.first->first << " " << range.first->second << endl; //prints 21 30, why?
    cout << range.second->first << " " << range.second->second << endl; //prints 21 30

}

prints
5 6
21 30
21 30
为什么set<pair<int,int>>上的equal_range不包括包含值(12)的范围,即[11.20]

5 个答案:

答案 0 :(得分:4)

equal_range表现完全正确:

assert( std::make_pair(11, 20) < std::make_pair(12, 12) );
assert( std::make_pair(12, 12) < std::make_pair(21, 30) );

[11,20]不是一个范围,它是一对。这对[12,12]不在“另一对”之内,甚至没有任何意义。

[12,12]不在“内”[11,20],它比它更大。 std::pair的小于运算符首先比较第一个元素,并且只有它们相等才会查看第二个元素,因此make_pair(11,x)小于make_pair(12, y) 任何xy

所以equal_range告诉你[12,20]会在[11,20]之后和[21,30]之前插入,这是正确的。

如果你想将对作为值的范围来处理你需要编写代码来做到这一点,不要假设对的内置比较就是这样做的。你实际上是想在一系列int中找到一个int 12,但是已经编写了代码来找到一对int的一对[12,12]。那不是一回事。

答案 1 :(得分:3)

该范围内不包含[11, 20],因为该范围内不包含任何[12, 12]没有相同的元素,因此它返回一个空范围(由半开区间[x, x)表示)。

BTW取消引用范围的上限可能会调用未定义的行为,因为它可能等于s.end()

答案 2 :(得分:1)

[12, 12][11, 20]之后和[21, 30]之前排序。

std::set::equal_range()包含一系列相等的元素。您的集合中没有相同的元素(尤其不是[11, 20]),因此equal_range()会返回[21, 30], [21, 30]

答案 3 :(得分:1)

实现

equal_range以先调用lower_bound,然后调用upper_bound来搜索其余数据集。

template <class ForwardIterator, class T>
  pair<ForwardIterator,ForwardIterator>
    equal_range ( ForwardIterator first, ForwardIterator last, const T& value )
{
  ForwardIterator it = lower_bound (first,last,value);
  return make_pair ( it, upper_bound(it,last,value) );
}

看看你的样本: 它调用lower_bound来定位值的下限(对(12,12),到达

pair<int,int> p[] = {make_pair(1,10), 
                     make_pair(11,20), 
                     make_pair(21,30),   // <--- lower_bound() points to here
                     make_pair(31,40)}; 

然后它调用upper_bound()来搜索(21,30),(31,40)并且它找不到它,它返回(21,30)

http://www.cplusplus.com/reference/algorithm/upper_bound/

答案 4 :(得分:1)

我不认为你的std::set<std::pair<int, int> >在与整数相交时不会对你有多大帮助:你可以找到s.lower_bound(std::make_pair(i + 1, i + 1)来切断搜索,但所有范围从索引开始都低于如果第二个边界足够大,i + 1可能包含值i。可能有帮助的是,如果您知道范围的最大大小,在这种情况下,您可以通过s.lower_bound(std::make_pair(i - max_range_size, i - max_range_size))将搜索范围限制在前面。您需要依次检查每个范围,以确定您的i是否属于它们:

auto it    = s.lower_bound(std::make_pair(i - max_range_size, i - max_range_size));
auto upper = s.lower_bound(std::make_pair(i + 1, i + 1));
for (; it != upper; ++it) {
    if (i < it->second) {
        std::cout << "range includes " << i << ": "
                  << [" << it.first << ", " << it->second << "]\n";
}

(或类似的东西......)