C++学习笔记(三十二)——priority_queue
一、 std::priority_queue
std::priority_queue
是 C++的STL 提供的优先级队列(Priority Queue),本质上是基于堆(Heap)实现的一个容器适配器。
特点:
- 默认是最大堆(Max Heap):
top()
返回最大元素 - 可以转换为最小堆(Min Heap) 或自定义比较方式
- 插入 (
push
) 和删除 (pop
) 复杂度为O(log n)
- 访问最大/最小值 (
top
) 复杂度为O(1)
适用场景:
- 求前 K 个最大/最小元素:使用最小堆(Min Heap) 。
- 任务调度、事件处理:使用
priority_queue
管理优先级 。 - 如果存储复杂对象并求最大或最小:推荐使用
struct
+operator<
或自定义比较类。
二、priority_queue
的常用函数
函数 | 作用 |
---|---|
push(value) | 插入一个元素 |
pop() | 移除堆顶元素 |
top() | 返回堆顶元素 |
size() | 返回元素个数 |
empty() | 判断队列是否为空 |
三、priority_queue
的基本使用
(1) 默认最大堆(Max Heap)
作用:
std::priority_queue
默认是最大堆,即 top()
始终返回最大值。
#include <iostream>
using namespace std;
#include <queue>
int main() {
priority_queue<int> pq; // 默认最大堆
pq.push(10);
pq.push(5);
pq.push(20);
pq.push(15);
cout << "Priority Queue (Max Heap): ";
while (!pq.empty()) {
cout << pq.top() << " "; // 输出最大元素
pq.pop(); // 移除最大元素
}
cout << endl;
system("pause");
return 0;
}
注意:
push(10) → {10}
push(5) → {10, 5}
push(20) → {20, 5, 10}
(自动维护最大堆)push(15) → {20, 15, 10, 5}
pop()
依次取出 20 → 15 → 10 → 5
第三次插入元素时(pq.push(20);
):
将元素20与其父节点元素10比较大小,互换位置,
维护每个节点的键值都大于或等于其子节点键值的规则:
(2) 最小堆(Min Heap)
作用:
默认情况下 priority_queue
是最大堆,但可以用 std::greater<int>
创建最小堆(即 top()
返回最小元素)。
示例:
#include <iostream>
using namespace std;
#include <queue>
#include <vector>
int main() {
priority_queue<int, vector<int>, greater<int>> minHeap; // 最小堆
minHeap.push(10);
minHeap.push(5);
minHeap.push(20);
minHeap.push(15);
cout << "Priority Queue (Min Heap): ";
while (!minHeap.empty())
{
cout << minHeap.top() << " ";
minHeap.pop();
}
cout << endl;
system("pause");
return 0;
}
注意:
std::priority_queue<Type, std::vector<Type>, std::greater<Type>>
Type
:数据类型(如int
)。std::vector<Type>
:底层容器(必须是std::vector
)。std::greater<Type>
:比较函数(默std::less<Type>
代表最大堆)。
四、priority_queue
的应用
(1) 自定义 struct
比较
作用:
如果 priority_queue
需要存储复杂对象,如 struct
,就需要自定义比较函数。
示例:
#include <iostream>
using namespace std;
#include <queue>
#include <string>
struct Task {
int priority;
string name;
// 自定义比较运算符,优先级高的排在前面
bool operator<(const Task& other) const
{
return priority < other.priority; // 默认最大堆
}
};
int main() {
priority_queue<Task> pq;
pq.push({ 3, "Low priority" });
pq.push({ 5, "Medium priority" });
pq.push({ 10, "High priority" });
while (!pq.empty())
{
cout << pq.top().name << endl;
pq.pop();
}
system("pause");
return 0;
}
分析:
- 任务
priority=10
最高,先出队。 - 任务
priority=5
其次,再出队。 - 任务
priority=3
最后出队。
(2) 使用 struct
+ 自定义 Compare
函数
作用:
如果需要最小堆(或者复杂排序规则),可以使用自定义比较类。
示例:
#include <iostream>
using namespace std;
#include <queue>
#include <string>
struct Task {
int priority;
string name;
};
// 自定义比较函数(升序)
struct CompareTask
{
bool operator()(const Task& a, const Task& b)
{
return a.priority > b.priority; // 最小堆
}
};
int main() {
priority_queue<Task, vector<Task>, CompareTask> pq;
pq.push({ 3, "Low priority" });
pq.push({ 5, "Medium priority" });
pq.push({ 10, "High priority" });
while (!pq.empty())
{
cout << pq.top().name << endl;
pq.pop();
}
system("pause");
return 0;
}
注意:
CompareTask
让priority
小的优先级高,变成最小堆。
(3) Top K 问题(求前 K 个最大元素)
示例:
#include <iostream>
using namespace std;
#include <queue>
#include <vector>
vector<int> topKElements(vector<int>& nums, int k)
{
priority_queue<int, vector<int>, greater<int>> minHeap;
for (int num : nums) // 创建最小堆,插入元素
{
minHeap.push(num);
if (minHeap.size() > k) // 若元素数大于K,则弹出最小值,保留前K个最大元素
minHeap.pop();
}
vector<int> result;
while (!minHeap.empty()) // 保存前K个最大元素
{
result.push_back(minHeap.top());
minHeap.pop();
}
return result;
}
int main() {
vector<int> nums = {10, 5, 20, 8, 25, 15};
int k = 3;
vector<int> result = topKElements(nums, k);
for (int num : result)
{
cout << num << " ";
}
cout << endl;
system("pause");
return 0;
}
注意:
- 维护一个大小为
k=3
的最小堆minHeap
,确保存储最大的k
个数。