C++笔记:std::priority_queue

默认读者已经知道堆的原理了,本文只介绍优先队列的使用方式。

cpp 复制代码
#include <queue>
template <class _Ty, 
class _Container = vector<_Ty>, 
class _Pr = less<typename _Container::value_type>>
class priority_queue;
参数 含义 默认值
_Ty 元素类型 必写
_Container 用来存储数据的底层容器,一般 vector vector
_Pr 比较规则,用于决定"谁排在前面" less

大根堆 or 小根堆

为什么 less → 大根堆greater → 小根堆

Compare 作用 结果
std::less<T> "a 的优先级 < b 的优先级" 即 a < b 返回 true → a 优先级低 大根堆(最大值排前)
std::greater<T> a > b 返回 true → a 优先级低 小根堆(最小值排前)

priority_queue 认为:

Compare(a, b) 返回 true → 表示 a 的优先级比 b 低

并不是比较谁大谁小,而是比较"谁的优先级低"。

底层容器的区别

默认是 vector,其实你基本永远用 vector

底层容器需要满足能随机访问元素(RandomAccessContainer):

底层容器 能否使用 说明
vector<T> ✔ 默认 性能最好、普遍使用
deque<T> ✔ 可以 不常用,不如 vector 快
list<T> ❌ 不行 不支持随机访问
set/map ❌ 完全不相关

实际工程中的选择:

永远用 vector

因为堆需要随机访问,vector 是连续内存,cache 友好 + push/pop/heap 操作性能最佳。

其他容器几乎没有使用场景。

比较规则的三种写法

使用 std::less / std::greater(基础类型用)

cpp 复制代码
priority_queue<int, vector<int>, less<int>> max_heap;
priority_queue<int, vector<int>, greater<int>> min_heap;

适用于:

  • int

  • double

  • string(已有 < 或 >)

但不适用于没有 < 操作符的自定义类型。

所以你也可以自己重载类的<操作符。但是要注意一个问题,优先队列的比较和该类实际的比较可能不尽相同。比如类里有id和val两个成员。可能在某些地方排序是按照id比较,但是优先队列里你想根据val值来比较,所以需要注意。

下面的例子先不管这么多,仅仅是使用介绍

cpp 复制代码
struct Node {
    int cost;

    bool operator<(Node const& other) const {
        return cost < other.cost; // 按 cost 排序
    }
};

现在你就可以:

cpp 复制代码
priority_queue<Node> max_heap;  // 默认 less → 大根堆

也就是:

  • less<Node> 等同于调用 Node::operator<

  • 所以堆顶是最大 cost 的 Node(大根堆)

你可以直接用下面操作得到小根堆:

cpp 复制代码
priority_queue<Node, vector<Node>, greater<Node>> min_heap;

因为 greater<Node> 会使用 operator>,而 operator> 默认基于 operator<

自定义仿函数

适合自定义结构体,比如:

cpp 复制代码
struct Node {
    int id;
    int cost;
};

你想按 cost 小的优先:

cpp 复制代码
struct Cmp {
    bool operator()(Node const& a, Node const& b) const {
        return a.cost > b.cost; // 小根堆
    }
};

priority_queue<Node, vector<Node>, Cmp> pq;

用 lambda(C++20 最推荐简洁写法)

cpp 复制代码
auto cmp = [](auto const& a, auto const& b){
    return a.cost > b.cost;
};

priority_queue<Node, vector<Node>, decltype(cmp)> pq(cmp);

但是:

  • Compare 类型要写 decltype(cmp)

  • 构造函数要传入 cmp

可读性比仿函数差一点,但更简洁。

priority_queue 常见成员函数

和queue基本一致

构造函数

cpp 复制代码
explicit priority_queue(const _Pr& _Pred);
priority_queue(const _Pr& _Pred, const _Container& _Cont);
priority_queue(const _Pr& _Pred, _Container&& _Cont);
template <class _InIt, enable_if_t<_Is_iterator_v<_InIt>, int> = 0>
priority_queue(_InIt _First, _InIt _Last, const _Pr& _Pred, const _Container& _Cont);//传迭代器,后两个可省略
相关推荐
hmbbcsm7 分钟前
python做题小记(八)
开发语言·c++·算法
读创商闻20 分钟前
崇明岛西滩湿地:离都市最近的候鸟观测笔记
笔记
再睡一夏就好30 分钟前
深入Linux线程:从轻量级进程到双TCB架构
linux·运维·服务器·c++·学习·架构·线程
蒙奇D索大33 分钟前
【11408学习记录】考研英语长难句拆解三步法:三步拆解2020年真题,攻克阅读难点
笔记·学习·考研·改行学it
悠闲漫步者40 分钟前
第2章 MCS-51单片机的串口和最小系统(学习笔记)
笔记·学习·51单片机
莫白媛1 小时前
Linux创作笔记综合汇总篇
linux·运维·笔记
特立独行的猫a1 小时前
C++开发中的Pimpl机制与类声明机制深度解析:现代C++的编译解耦艺术
开发语言·c++·pimpl
GoWjw1 小时前
在C&C++指针的惯用方法
c语言·开发语言·c++
君义_noip1 小时前
信息学奥赛一本通 1453:移动玩具 | 洛谷 P4289 [HAOI2008] 移动玩具
c++·算法·信息学奥赛·csp-s
superman超哥1 小时前
仓颉语言中错误恢复策略的深度剖析与工程实践
c语言·开发语言·c++·python·仓颉