std::priority_queue
是 C++ STL 提供的 优先队列,它是一种 最大堆(默认情况下),可以用于高效地获取当前最大(或最小)的元素。
1. 基本用法
(1) 头文件
要使用 std::priority_queue
,需要包含:
#include <queue>
#include <vector>
#include <iostream>
(2) 默认情况(最大堆)
默认情况下,std::priority_queue
是 最大堆,即 堆顶是最大元素:
std::priority_queue<int> pq; // 默认是最大堆
示例:
#include <iostream>
#include <queue>
int main() {
std::priority_queue<int> pq;
pq.push(10);
pq.push(30);
pq.push(20);
std::cout << "堆顶元素:" << pq.top() << std::endl; // 输出 30
pq.pop(); // 移除 30
std::cout << "新的堆顶:" << pq.top() << std::endl; // 输出 20
return 0;
}
✅ 特点
push()
插入元素,自动维护最大堆。top()
获取当前最大元素(堆顶)。pop()
移除堆顶元素(但不返回它)。size()
获取队列大小。empty()
检查队列是否为空。
2. 自定义最小堆
如果要实现 最小堆(堆顶是最小元素),可以用 std::greater<T>
:
std::priority_queue<int, std::vector<int>, std::greater<int>> pq_min;
示例:
#include <iostream>
#include <queue>
int main() {
std::priority_queue<int, std::vector<int>, std::greater<int>> pq_min;
pq_min.push(10);
pq_min.push(30);
pq_min.push(20);
std::cout << "堆顶元素:" << pq_min.top() << std::endl; // 输出 10
pq_min.pop();
std::cout << "新的堆顶:" << pq_min.top() << std::endl; // 输出 20
return 0;
}
✅ 重点
std::greater<int>
使priority_queue
变成 最小堆。
3. 自定义比较函数(结构体/仿函数)
(1) 结构体仿函数
struct Compare {
bool operator()(int a, int b) {
return a > b; // 最小堆(a > b 表示 a 在 b 下面)
}
};
std::priority_queue<int, std::vector<int>, Compare> pq;
示例:
#include <iostream>
#include <queue>
struct Compare {
bool operator()(int a, int b) {
return a > b; // 让小的元素优先级高
}
};
int main() {
std::priority_queue<int, std::vector<int>, Compare> pq;
pq.push(10);
pq.push(30);
pq.push(20);
std::cout << "堆顶元素:" << pq.top() << std::endl; // 输出 10
pq.pop();
std::cout << "新的堆顶:" << pq.top() << std::endl; // 输出 20
return 0;
}
✅ 优点
- 适用于复杂的数据结构(如
struct
)。 - 允许灵活定义优先级。
4. 处理结构体类型
如果 priority_queue
存储的是 自定义结构体,需要提供比较规则。
(1) 按权重排序的任务调度
#include <iostream>
#include <queue>
struct Task {
int id;
int priority;
// 重载运算符,用于最大堆(优先级大的优先)
bool operator<(const Task& other) const {
return priority < other.priority; // 优先级高的排前面
}
};
int main() {
std::priority_queue<Task> pq;
pq.push({
1, 3});
pq.push({
2, 5});
pq.push({
3, 1});
std::cout << "最高优先级任务 ID:" << pq.top().id << std::endl; // 输出 2
pq.pop();
std::cout << "新的最高优先级任务 ID:" << pq.top().id << std::endl; // 输出 1
return 0;
}
✅ 特点
- 默认是最大堆,因此
operator<
定义为 优先级小的在下面。
(2) 使用自定义比较函数
如果不能修改 struct
,可以使用 外部比较函数:
struct CompareTask {
bool operator()(const Task& a, const Task& b) {
return a.priority > b.priority; // 最小堆
}
};
std::priority_queue<Task, std::vector<Task>, CompareTask> pq;
完整示例:
#include <iostream>
#include <queue>
struct Task {
int id;
int priority;
};
// 使 priority_queue 变成最小堆
struct CompareTask {
bool operator()(const Task& a, const Task& b) {
return a.priority > b.priority; // 小优先级的任务优先
}
};
int main() {
std::priority_queue<Task, std::vector<Task>, CompareTask> pq;
pq.push({
1, 3});
pq.push({
2, 5});
pq.push({
3, 1});
std::cout << "最高优先级任务 ID:" << pq.top().id << std::endl; // 输出 3
pq.pop();
std::cout << "新的最高优先级任务 ID:" << pq.top().id << std::endl; // 输出 1
return 0;
}
✅ 适用场景
- 优先队列调度算法
- 事件驱动仿真
- A 搜索(最短路径算法)*
5. priority_queue
适用场景
应用场景 | 用法 |
---|---|
最大堆(默认) | std::priority_queue<int> |
最小堆 | std::priority_queue<int, std::vector<int>, std::greater<int>> |
存储结构体(最大堆) | 结构体重载 < |
存储结构体(最小堆) | std::greater<> 或自定义 Compare |
K 大/小元素 | 维护大小为 K 的堆 |
Dijkstra / A 搜索* | 结合 std::pair<int, int> 进行路径计算 |
6. 经典应用示例
(1) 找到前 K 个最大元素
#include <iostream>
#include <queue>
#include <vector>
void findTopK(std::vector<int>& nums, int k) {
std::priority_queue<int, std::vector<int>, std::greater<int>> pq; // 最小堆
for (int num : nums) {
pq.push(num);
if (pq.size() > k) pq.pop(); // 只保留 k 个最大值
}
std::cout << "前 " << k << " 个最大元素:" << pq.top() << std::endl;
}
int main() {
std::vector<int> nums = {
3, 1, 5, 12, 2, 11};
findTopK(nums, 3); // 输出 5
}
✅ 复杂度:O(N log K)
总结
std::priority_queue
默认是 最大堆,可以用std::greater<>
实现 最小堆。- 存储结构体时,可以使用 重载
<
运算符 或 自定义比较器。 - 适用于 任务调度、路径搜索(Dijkstra/A)等场景*。