priority_queue 默认是大根堆,top() 返回最大元素;存入 {3,1,4} 后 top() 为 4,pop 顺序为 4→3→1;需小根堆时须自定义比较器。

priority_queue 默认是大根堆还是小根堆
默认是大根堆——也就是说,top() 返回的是最大元素。这和很多人直觉里“优先级高就先出队”一致,但容易误以为“优先级数值小才该先出”,结果在实现最小堆逻辑时忘了改比较器。
常见错误现象:priority_queue<int> q;</int> 存入 {3,1,4} 后调用 q.top() 得到 4,不是 1;想做升序输出却直接 pop,结果顺序是 4→3→1,不是预期的 1→3→4。
- 要小根堆:用
priority_queue<int vector>, greater<int>></int></int> - 自定义类型必须提供可比较的
operator 或传入仿函数,否则编译报错 <code>invalid operands to binary expression - 注意
greater<int></int>在头文件<functional>里,漏引会编译失败
如何用 priority_queue 实现堆排序(非原地)
它不能直接替代 std::sort 做高效原地排序,但能以 O(n log n) 时间、O(n) 空间完成升序或降序排列——关键是“先全塞进去,再逐个取 top() 并 pop()”。
使用场景:数据流中动态维护 Top-K,或已有容器需按优先级重排且不介意额外空间。
立即学习“C++免费学习笔记(深入)”;
- 升序输出(即小根堆):用
priority_queue<int vector>, greater<int>></int></int> - 降序输出(即大根堆):直接用默认
priority_queue<int></int> - 别在循环里反复调用
push()+top()模拟排序逻辑——那是 O(n²),老老实实先建堆再清空
示例(升序):
vector<int> v = {3, 1, 4, 1, 5};
priority_queue<int, vector<int>, greater<int>> pq(v.begin(), v.end());
while (!pq.empty()) {
cout << pq.top() << " "; // 输出 1 1 3 4 5
pq.pop();
}
自定义比较器写法及常见翻车点
lambda 不能直接用于模板参数(因为类型不可名),必须用函数对象(struct)或 std::function 包装——但后者有性能开销,一般不用。
错误现象:写 priority_queue<point vector>, [](const Point& a, const Point& b) { return a.x </point> 编译不过,报错类似 type name is not allowed。
- 正确做法:定义 struct,重载
operator(),比如struct CompareX { bool operator()(const Point& a, const Point& b) { return a.x > b.x; } };,然后用priority_queue<point vector>, CompareX></point> - 注意返回值语义:函数对象返回
true表示a应该排在b后面(即a优先级更低),所以想按x升序,得写a.x > b.x - 如果比较逻辑复杂或依赖外部状态,考虑提前计算好 key 存入 pair,避免运行时重复计算
和 make_heap / sort_heap 的性能与适用差异
priority_queue 是容器适配器,底层默认用 vector,建堆 O(n),单次 push/pop O(log n);而 make_heap 直接操作原始容器,更轻量,但需要手动管理堆结构。
性能影响:频繁单元素插入/删除时,priority_queue 更安全;一次性建堆+批量读取,make_heap + sort_heap 内存局部性更好、少一层封装开销。
- 想复用已有
vector数据且不希望拷贝,用make_heap(v.begin(), v.end()),之后pop_heap+v.pop_back()手动维护 -
priority_queue不提供迭代器,无法遍历中间状态;make_heap后的容器仍是普通vector,可随意访问 - 兼容性上无差别,都是 C++98 起支持,但
priority_queue语法更简洁,适合快速原型
真正容易被忽略的是:当你需要“修改堆中某个元素的优先级”,priority_queue 不支持——只能标记删除+重新插入,或者换用 std::set 或带索引的堆实现。











