45 C++ STL模板库14-容器6-容器适配器-优先队列(priority_queue)
STL模板库-容器6-容器适配器-优先队列(priority_queue)
文章目录
- STL模板库-容器6-容器适配器-优先队列(priority_queue)
- 1. 成员类型
- 2. 构造函数
- 3. 核心成员函数
- (1). 容量操作
- (2). 元素访问
- (3). 修改操作
- (4). 交换操作
- 4. 非成员函数
- 5. 底层容器与比较器
- 6. 关键特性与注意事项
- 7. 完整示例
priority_queue
是一个容器适配器,默认基于
std::vector
实现,元素按优先级(默认最大堆)排序,定义在
<queue>
头文件中。
priority_queue
提供了高效的动态优先级管理,核心操作围绕堆顶元素展开,适合需要频繁插入和删除最高/最低优先级元素的场景。通过自定义容器和比较器,可灵活适配不同需求。
1. 成员类型
类型名称 | 描述 |
---|---|
value_type | 元素类型(模板参数 T ) |
container_type | 底层容器类型(默认 vector<T> ) |
size_type | 表示大小的无符号整数(如 size_t ) |
reference | 元素的引用(如 T& ) |
const_reference | 元素的常量引用(如 const T& ) |
2. 构造函数
构造函数签名 | 说明 |
---|---|
priority_queue() | 默认构造空队列 |
explicit priority_queue(const Compare& comp) | 指定比较器(如 std::greater<T> ) |
priority_queue(const Compare& comp, Container&& c) | 用底层容器初始化(可移动或拷贝) |
template <class InputIt> priority_queue(InputIt first, InputIt last, ...) | 通过迭代器范围构造 |
3. 核心成员函数
(1). 容量操作
函数签名 | 功能描述 | 时间复杂度 |
---|---|---|
bool empty() const | 检查队列是否为空 | O(1) |
size_type size() const | 返回元素数量 | O(1) |
(2). 元素访问
函数签名 | 功能描述 | 时间复杂度 |
---|---|---|
const_reference top() const | 返回堆顶元素(最高优先级) | O(1) |
(3). 修改操作
函数签名 | 功能描述 | 时间复杂度 |
---|---|---|
void push(const T& value) | 插入元素(拷贝语义) | O(log n) |
void push(T&& value) | 插入元素(移动语义,C++11起) | O(log n) |
template <class... Args> void emplace(Args&&... args) | 直接构造元素(避免拷贝) | O(log n) |
void pop() | 移除堆顶元素 | O(log n) |
(4). 交换操作
函数签名 | 功能描述 | 时间复杂度 |
---|---|---|
void swap(priority_queue& other) noexcept | 交换两个队列内容(C++11起) | O(1) |
4. 非成员函数
函数签名 | 说明 |
---|---|
void swap(priority_queue<T>& a, priority_queue<T>& b) | 全局交换函数(同成员函数) |
5. 底层容器与比较器
-
底层容器要求:
必须支持front()
,push_back()
,pop_back()
和随机访问迭代器(如vector
或deque
)。 -
自定义比较器:
// 示例:最小堆(优先级小的先出队) priority_queue<int, vector<int>, greater<int>> minHeap;
6. 关键特性与注意事项
-
无迭代器:无法直接遍历元素,只能通过
top()
和pop()
遍历元素(会清空队列) -
性能特点:插入和删除操作的时间复杂度为 O(log n),堆顶访问为 O(1)。
-
默认行为:最大堆(
std::less<T>
比较器)。 -
底层容器:默认
vector
,可替换为deque
(需支持随机访问和pop_back
) -
比较器规则:返回
true
表示 左参数优先级更低// 自定义比较函数示例 auto cmp = [](int a, int b) { return a > b; }; std::priority_queue<int, std::vector<int>, decltype(cmp)> customHeap(cmp);
-
适用场景:任务调度、Dijkstra算法、Top K问题等需要动态排序的场景。
7. 完整示例
#include <iostream>
#include <queue>
#include <vector>
#include <functional> // std::greater int main() {// ===== 1. 基础用法(默认最大堆)=====std::priority_queue<int> maxHeap; // 默认:大值优先maxHeap.push(30); maxHeap.push(10); maxHeap.emplace(50); // 直接构造元素std::cout << "最大堆顶部: " << maxHeap.top() << "\n"; // 50 // ===== 2. 自定义排序规则 =====// 最小堆(小值优先)std::priority_queue<int, std::vector<int>, std::greater<int>> minHeap;minHeap.push(30); minHeap.push(10); std::cout << "最小堆顶部: " << minHeap.top() << "\n\n"; // 10 // ===== 3. 使用自定义容器初始化 ===== std::vector<int> nums{15, 25, 5};std::priority_queue<int> q(nums.begin(), nums.end()); std::cout << "容器初始化堆顶: " << q.top() << "\n"; // 25// ===== 4. 完整操作示例 ===== std::priority_queue<std::string> tasks;// 添加元素tasks.push(" 写报告");tasks.emplace(" 调试代码"); tasks.push(" 会议准备");// 容量查询 std::cout << "\n任务数量: " << tasks.size(); // 3std::cout << "\n是否为空: " << (tasks.empty() ? "是" : "否") << "\n\n"; // 否// 访问并移除元素(按字典序降序)std::cout << "任务处理顺序:\n";while (!tasks.empty()) {std::cout << "正在处理: " << tasks.top() << "\n"; // 调试代码 -> 写报告 -> 会议准备tasks.pop(); }std::cout << "剩余任务: " << tasks.size(); // 0return 0;
}
输出结果:
最大堆顶部: 50
最小堆顶部: 10容器初始化堆顶: 25
任务数量: 3
是否为空: 否任务处理顺序:
正在处理: 调试代码
正在处理: 写报告
正在处理: 会议准备
剩余任务: 0
- 使用方法详解
📦 构造初始化方式
| 方法 | 示例 | 说明 |
|------|------|------|
| 默认构造 |priority_queue<int> maxHeap;
| 最大堆(大值优先) |
| 自定义比较器构造 |priority_queue<int, vector<int>, greater<int>> minHeap;
| 最小堆(小值优先) |
| 容器初始化 |priority_queue<int> q(vec.begin(), vec.end());
| 通过迭代器范围构造 |
⚙️ 元素操作
操作 | 函数 | 特性 |
---|---|---|
添加元素 | push(val) / emplace(args...) | emplace 避免拷贝,效率更高 |
访问顶部 | top() | 只读操作,不改变堆结构 |
移除顶部 | pop() | 移除当前最高优先级元素 |
容量查询 | size() / empty() | 常数时间复杂度 O(1) |
🔄 高级操作
// 交换两个优先队列
std::priority_queue<int> pq1, pq2;
pq1.swap(pq2); // 自定义数据结构排序
struct Task {int priority;std::string name;bool operator<(const Task& t) const { return priority < t.priority; // 按优先级降序}
};
std::priority_queue<Task> taskQueue;