如何重载'<' (小于)一对int的运算符,用于将此类元素插入set中。例如,请考虑以下程序
#include <stdio.h>
#include <utility>
#include <set>
using namespace std;
bool operator<(pair<int, int> a, pair<int, int> b){
if(a.second < b.second) return true;
if(a.second == b.second) return a.first < b.first;
return false;
}
int main(){
pair<int, int> a = make_pair(1, 4);
pair<int, int> b = make_pair(2, 3);
set<pair<int ,int> > s;
s.insert(b);
s.insert(a);
set<pair<int, int> >::iterator it = s.begin();
for(; it!=s.end(); it++){
printf("(%d %d)\n", it->first, it->second);
}
if(a < b) printf("a < b\n");
else printf("b < a\n");
}
上述代码产生的输出是:
(1 4)
(2 3)
b < a
我希望集合的元素由对结构的第二个元素排序。怎么做?
答案 0 :(得分:3)
问题在于std::set
在内部使用std::less
进行比较,并委派给标准库提供的operator<
std::pair
。这会在first
然后second
按字典顺序排列您的对。
但是,您还需要提取整个namespace std
并提供自己的operator<
。在您执行if(a<b)
时,名称查找将找到您自己提供的比较并使用它。这就是你得到矛盾结果的原因。
您可以编写自己的函数对象my_less
并将其传递给std::set
。我建议您使用std::forward_as_tuple
,但您提供的实施也可以。
#include <stdio.h>
#include <utility>
#include <set>
#include <tuple>
using namespace std;
struct my_less
{
bool operator()(pair<int, int> const& a, pair<int, int> const& b) const
{
return std::forward_as_tuple(a.second, a.first) < std::forward_as_tuple(b.second, b.first);
}
};
int main(){
pair<int, int> a = make_pair(1, 4);
pair<int, int> b = make_pair(2, 3);
set<pair<int ,int>, my_less> s;
s.insert(b);
s.insert(a);
set<pair<int, int> >::iterator it = s.begin();
for(; it!=s.end(); it++){
printf("(%d %d)\n", it->first, it->second);
}
if(my_less{}(a,b)) printf("a < b\n");
else printf("b < a\n");
}
答案 1 :(得分:2)
std::set
维护其元素之间的顺序(每个值也是它自己的键,因此它必须是唯一的。)
您无法对std::set
进行排序并破坏此排序,但您可以定义自己的排序标准
struct sortBySecond {
bool operator()(const pair<int, int>& e1, const pair<int, int>& e2) const {
if (e1.second < e2.second)
return true;
else if (e1.second == e2.second) {
if (e1.first < e2.first)
return true;
else
return false;
}
else
return false;
}
};
int main() {
pair<int, int> a = make_pair(1, 4);
pair<int, int> b = make_pair(2, 3);
set<pair<int, int>, sortBySecond> s;
s.insert(b);
s.insert(a);
for (auto& el : s)
std::cout << "(" << el.first << ";" << el.second << ")" << std::endl;
return 0;
}