priority_queue默认是大根堆,仅支持访问顶部极值,不提供遍历或清空接口;需排序用vector+sort或set,需动态极值选priority_queue;小根堆用greater,自定义类型需重载operator

priority_queue 默认是大根堆,不是排序数组
很多人一看到 priority_queue 就以为能当“自动排序容器”用,结果 top() 只能取最大(或最小)元素,不能遍历有序序列。它本质是堆,不是 std::set 或 std::vector 配 std::sort。
常见错误现象:for (auto x : pq) 编译失败;或者手动 pop 所有元素想“导出排序结果”,却发现顺序只在每次 top() + pop() 时局部有效,且破坏原队列。
- 真正需要排序列表 → 改用
std::vector+std::sort或std::set - 只需要动态维护极值(如 Top-K、合并 K 个有序链表)→
priority_queue正确场景 - 默认模板参数是
std::less<t></t>,所以priority_queue<int></int>是大根堆,最大值在顶
怎么让 priority_queue 变成小根堆
默认大根堆不够用?别写循环翻转,直接换比较器。最常用的是用 std::greater<int></int>,但注意它要求头文件 <functional></functional>。
容易踩的坑:priority_queue<int vector>, greater<int>></int></int> 看似对,但漏了模板参数里的容器类型声明,编译报错 template argument 2 is invalid;还有人误写 greater(C++14+ 才支持),在老项目里直接跪。
立即学习“C++免费学习笔记(深入)”;
- 标准写法:
priority_queue<int vector>, greater<int>></int></int> - 自定义类型必须提供可比较操作:要么重载
operator(注意:大根堆用 <code>,小根堆要反过来逻辑) - 或者传 lambda —— 但 C++ 标准库不接受 lambda 作为模板非类型参数,得包一层
function或用函数对象类
push 和 emplace 性能差在哪
push 先构造临时对象再移动/拷贝进堆;emplace 直接在堆内存里原地构造。对带参构造的类(比如 pair<string int></string>),emplace 能省一次构造+一次移动。
但别无脑换:emplace 对内置类型(int、double)没区别;而且如果参数本身是已存在的对象(比如 emplace(x),而 x 是个现成的 string),反而可能触发隐式转换或额外拷贝。
- 推荐场景:
emplace(1, "hello")构造pair<int string></int>,比push(pair<int>(1,"hello"))</int>更干净 - 慎用场景:
emplace(some_string),不如push(some_string)直观安全 - 所有
emplace调用都走完美转发,参数类型错位会报一堆模板错误,调试比push痛
清空 priority_queue 没有 clear() 成员函数
标准 priority_queue 不提供 clear(),这是有意设计:堆结构不鼓励频繁清空,而是建议作用域控制或交换空队列。
常见错误做法:循环 pop() 直到 empty() —— 看似可行,但时间复杂度是 O(n log n),远不如直接重建。
- 安全高效做法:
q = decltype(q)();(C++11+),等价于用默认构造覆盖 - 或者 swap:
priority_queue<int> empty_q; q.swap(empty_q);</int> - 如果在类成员里频繁清空,考虑是否真需要持久化队列——也许局部新建更合适
底层没有迭代器暴露,也没办法像 vector 那样直接 resize(0)。接受这个限制,比硬套 workaround 更稳。








