如何在对对上使用lower_bound()?

时间:2019-03-28 08:09:11

标签: c++

我给了一个std::set<std::pair<int,int>>和一个整数x,我必须找到第一个对的迭代器,它的第一个元素大于或等于给定的整数x

我了解到,如果sset<pair<int, int>>,而{x, y}是一对,那么我可以使用s.lower_bound({x, y})。但是,就我而言,我只需要关心第一个元素x。因此,我的问题是,当我只关心第一个元素时,如何在lower_bound上使用set<pair<int, int>>

2 个答案:

答案 0 :(得分:5)

核心问题是您的std::set实例已经排序,但默认值为std::pair operator<。您不能直观地使用成员函数std::set::lower_bound,因为它使用了其类类型的比较函数。您不能将std::lower_bound与自定义谓词一起使用,因为它假定了排序范围-而是针对给定谓词进行了排序,并非如此。

但是对于这种特定情况,有一种解决方法。请注意,对于集合中每个x的值,y的最小关联值是类型int的最小值。当std::pair实例的比较运算符进行成员比较时,您可以将其组合为:

#include <set>
#include <limits>

const std::set<std::pair<int,int>> s{
   {42, 0}, {42, 1}, {43, 0}, {43, 1}
};

const auto entry = s.lower_bound({43, std::numeric_limits<int>::min()});

这将始终在子集中找到与std::pair::first数据成员的给定值相对应的 first minimum 所需的条目。只有第一个值才有意义,因为第二个值立即不小于 std::numeric_limits<int>::min(),这就是lower_bound正在搜索的内容。

如果您多次需要此功能,可能值得将其放入自己的帮助器功能(模板)中,例如

template <class T>
auto lower_bound_first(const std::set<std::pair<T, T>>& s, T first)
{
   static constexpr T min = std::numeric_limits<T>::min();

   return s.lower_bound({first, min});
}

您可以调用为

const auto entry = lower_bound_first(s, 43);

适用于std::numeric_limits专长专用的任何基础值类型。

答案 1 :(得分:1)

有一种方法无需构造临时pair。一个需要的是在该对和另一种类型之间定义operator<。为了避免弄乱operator<pair的{​​{1}}的全局定义,请为包装器定义它:

int

这对于template <class T> struct Wrapper { T value; }; template <class T> bool operator<(const std::pair<T, T> & x, Wrapper<T> value) { return x.first < value.value; } template <class T> bool operator<(Wrapper<T> value, const std::pair<T, T> & x) { return value.value < x.first; } int main() { // NOTE: using std::less<>, instead of the default std::less<std::pair<int, int>> std::set<std::pair<int, int>, std::less<>> s {{1,2}, {1,3}, {4,1}, {5,1}, {5,2}}; Wrapper<int> x{2}; auto it = s.lower_bound(x); 来说是一个矫kill过正,但是对于像std::pair<int, int>这样的更复杂的类型,构造尽可能小的对象可能会很昂贵。另外,对于无限精度数字,不存在这样的值。在这种情况下,必须采用上述技术。对于更复杂的类型,可以简单地重载std::pair<int, MyFancyClass>,而无需使用包装器。

请注意,重载的运算符必须彼此一致。它们必须服从相同的元素顺序。