C++的priority_queue属于容器适配器,底层默认基于vector实现,遵循大顶堆的规则,队首元素始终是队列中优先级最高的元素,也就是默认情况下最大的元素。它在很多需要频繁获取最值的场景中非常实用,比如任务调度、TopK问题求解等。

priority_queue基本用法
头文件与定义
使用priority_queue需要先包含头文件<queue>,默认的定义方式如下:
#include <queue>
#include <iostream>
using namespace std;
int main() {
// 默认大顶堆,队首是最大的元素
priority_queue<int> pq;
return 0;
}
常用成员函数
priority_queue的常用操作比较少,主要包含以下几个:
- push(const T& val):向优先队列中插入元素,插入后会自动调整堆结构保证队首是优先级最高的元素
- pop():删除队首元素,删除后同样会调整堆结构
- top():返回队首元素的引用,注意不会删除该元素
- empty():判断队列是否为空,为空返回true,否则返回false
- size():返回队列中元素的个数
下面是一个基本用法的示例:
#include <queue>
#include <iostream>
using namespace std;
int main() {
priority_queue<int> pq;
// 插入元素
pq.push(3);
pq.push(1);
pq.push(5);
pq.push(2);
// 输出队首元素,此时应该是5
cout << "队首元素:" << pq.top() << endl;
// 删除队首元素
pq.pop();
// 再次输出队首元素,此时应该是3
cout << "删除后队首元素:" << pq.top() << endl;
// 遍历所有元素,注意优先队列不支持直接遍历,需要逐个弹出
cout << "所有元素从大到小:" ;
while (!pq.empty()) {
cout << pq.top() << " ";
pq.pop();
}
cout << endl;
return 0;
}
priority_queue自定义排序方法
默认的priority_queue是大顶堆,如果我们想要小顶堆,或者按照自定义的规则排序,就需要传入自定义的比较方式,常见的有以下三种方法。
方法一:使用标准库提供的比较函数对象
对于基础数据类型,我们可以使用<functional>头文件中的greater<T>来实现小顶堆,定义时需要传入两个模板参数,第一个是元素类型,第二个是底层容器类型,第三个是比较规则。底层容器默认是vector,所以通常可以省略第二个参数,只传第三个参数。
#include <queue>
#include <functional>
#include <iostream>
using namespace std;
int main() {
// 小顶堆,队首是最小的元素
priority_queue<int, vector<int>, greater<int>> min_pq;
min_pq.push(3);
min_pq.push(1);
min_pq.push(5);
min_pq.push(2);
cout << "小顶堆队首元素:" << min_pq.top() << endl; // 输出1
return 0;
}
方法二:自定义比较结构体
当我们需要更复杂的排序规则时,可以自定义一个比较结构体,重载operator()函数,在函数内定义比较规则。注意priority_queue的比较规则和sort是相反的,sort中返回true表示第一个参数排在第二个前面,而priority_queue中返回true表示第一个参数的优先级比第二个低。
比如我们要定义一个存储学生信息的优先队列,按照学生的分数从高到低排序,分数相同按照年龄从小到大排序:
#include <queue>
#include <string>
#include <iostream>
using namespace std;
struct Student {
string name;
int score;
int age;
};
// 自定义比较结构体
struct StudentCompare {
bool operator()(const Student& a, const Student& b) const {
// 分数高的优先级高,所以分数低的优先级低,返回true
if (a.score != b.score) {
return a.score < b.score;
}
// 分数相同,年龄小的优先级高,所以年龄大的优先级低,返回true
return a.age > b.age;
}
};
int main() {
priority_queue<Student, vector<Student>, StudentCompare> stu_pq;
stu_pq.push({"张三", 90, 20});
stu_pq.push({"李四", 95, 19});
stu_pq.push({"王五", 90, 18});
// 输出队首学生,应该是李四,分数最高
Student top_stu = stu_pq.top();
cout << "最高分学生:" << top_stu.name << " 分数:" << top_stu.score << " 年龄:" << top_stu.age << endl;
stu_pq.pop();
// 接下来是张三和王五分数相同,王五年龄小,所以王五优先
top_stu = stu_pq.top();
cout << "第二高分学生:" << top_stu.name << " 分数:" << top_stu.score << " 年龄:" << top_stu.age << endl;
return 0;
}
方法三:使用lambda表达式配合decltype
C++11之后我们还可以使用lambda表达式来定义比较规则,这时候需要注意定义priority_queue时需要传入lambda的类型,通常用decltype来获取,同时需要在构造函数中传入lambda表达式作为比较对象。
#include <queue>
#include <iostream>
#include <functional>
using namespace std;
int main() {
// 定义lambda表达式,实现小顶堆
auto cmp = [](int a, int b) {
return a > b; // a比b大的时候,a的优先级比b低,所以是小顶堆
};
// 定义优先队列,模板参数需要decltype(cmp)
priority_queue<int, vector<int>, decltype(cmp)> pq(cmp);
pq.push(3);
pq.push(1);
pq.push(5);
pq.push(2);
cout << "小顶堆队首:" << pq.top() << endl; // 输出1
return 0;
}
注意事项
- priority_queue不支持随机访问,只能通过top()访问队首元素,没有迭代器,不能直接遍历所有元素
- 自定义比较规则的时候要注意和sort的比较规则相反,避免逻辑错误
- 如果存储的是自定义类型,需要保证比较规则中不会修改元素的值,最好将operator()定义为const成员函数
- 插入和删除元素的时间复杂度都是O(log n),获取队首元素的时间复杂度是O(1),效率比较高
priority_queue优先队列自定义排序C++修改时间:2026-07-01 02:00:42