C++怎么使用优先队列_C++priority_queue教程【排序】

2次阅读

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

C++怎么使用优先队列_C++priority_queue教程【排序】

priority_queue 默认是大根堆,不是排序数组

很多人一看到 priority_queue 就以为能当“自动排序容器”用,结果 top() 只能取最大(或最小)元素,不能遍历有序序列。它本质是堆,不是 std::setstd::vectorstd::sort

常见错误现象:for (auto x : pq) 编译失败;或者手动 pop 所有元素想“导出排序结果”,却发现顺序只在每次 top() + pop() 时局部有效,且破坏原队列。

  • 真正需要排序列表 → 改用 std::vector + std::sortstd::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;还有人误写 greaterc++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 对内置类型(intdouble)没区别;而且如果参数本身是已存在的对象(比如 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 更稳。

text=ZqhQzanResources