为何重载std::tuple的operator<在priority_queue中未生效?
问题根源
你定义的operator<完全没被priority_queue用到。原因很简单:std::tuple本身在std命名空间里已经有默认的operator<重载了,当priority_queue用默认的std::less<>比较器时,编译器会自动找到std里的版本,直接忽略你在全局写的那个重载。
而std::tuple默认的比较逻辑是按元素顺序依次对比:先比第一个元素,相等就比第二个,再相等比第三个。你插入的两个tuple第一个元素都是2,第二个元素5比3大,所以默认逻辑里(2,5,3)是"更大"的那个。priority_queue默认是大顶堆,堆顶永远是最大的元素,所以不管你怎么改自己写的operator<,输出都是5。
正确实现方式
别去重载全局的operator<,直接给priority_queue传自定义比较器就行:
#include <iostream> #include <tuple> #include <queue> using namespace std; // 自定义比较器:按第二个元素的大小来调整堆的优先级 struct CompareBySecond { bool operator()(const tuple<int, int, int>& lhs, const tuple<int, int, int>& rhs) { // priority_queue的规则:返回true时,lhs的优先级比rhs低,会被放到堆的下层 // 想要大顶堆(第二个元素大的在堆顶)就写 <,想要小顶堆就写 > return get<1>(lhs) < get<1>(rhs); } }; int main() { // 必须显式指定底层容器(这里用vector)和自定义比较器 priority_queue<tuple<int, int, int>, vector<tuple<int, int, int>>, CompareBySecond> q; q.push(make_tuple(2, 5, 3)); q.push(make_tuple(2, 3, 3)); cout << get<1>(q.top()); // 此时输出5(大顶堆),如果把比较器里的<改成>,就会输出3 return 0; }
这样就能完全按照你想要的逻辑控制堆的排序了。
内容的提问来源于stack exchange,提问作者MKCCT
相关产品推荐
相关产品推荐

