用途
优先队列,保证每次的队首元素都是优先级最大的。可以用来解决一些贪心问题,也可以对 Dijkstra 算法进行优化(优先队列的本质是堆)。
头文件
# include <queue>
定义
priority_queue<Type, Container, Functional>
Type为数据类型, Container为保存数据的容器,Functional为元素比较方式。
如果不写后两个参数,那么容器默认用的是vector,比较方式默认用operator<,也就是优先队列是大根堆,队头元素最大。
容器内元素访问
与队列不同,优先队列只能通过 top() 函数来访问队首元素,见下方。
常用函数
q.push(x)
: 将 x 入队。q.pop()
:将队首元素出队。q.top()
:获得队首元素。q.empty()
:检测队列是否为空,返回 true 则为空,返回 false 则非空。q.size()
:返回队列中元素的个数。
注意:使用 top() 和 pop() 函数前,应当先用 empty() 判断队列是否为空。
priority_queue 内元素优先级的设置
基本数据类型的优先级设置
priority_queue<int> q;
priority_queue<int, vector<int>, less<int>> q;
以上两句是等价的。第二句中,第二个参数 vector<int>
填写的是来承载底层数据结构堆的容器,如果第一个参数是 double 型就填写 vector<double>
,第一个参数是 char 型就填写 vector<char>
。第三个参数 less<int>
表示数字大的优先级大(默认情况)。若想让数字小的优先级大,则改为 greater<int>
。
priority_queue<int, vector<int>, greater<int> > q; //注意两个 > 之间需加空格
q.push(3);
q.push(4);
q.push(1);
printf("%d", q.top());
输出结果:
1
自定义数据类型的优先级设置
例如,对水果的名称和价格建立一个结构体,现在希望按水果的价格高的为优先级高,写法如下:
# include <stdio.h>
# include <vector>
# include <queue>
# include <string>
# include <iostream>
using namespace std;
// 方法1:
// 重载 < 操作符
// struct fruit
// {
// string name;
// int price;
// friend bool operator < (const fruit &f1, const fruit &f2);
// };
// bool operator < (const fruit &f1, const fruit &f2){
// return f1.price < f2.price;
// }
// 方法2:
// 自定义比较函数
struct fruit
{
string name;
int price;
};
struct cmp{
bool operator() (const fruit &f1, const fruit &f2){
return f1.price < f2.price;
}
};
int main(){
priority_queue<fruit, vector<fruit>, cmp> q;
fruit f1, f2, f3;
f1.name = "banana";
f1.price = 3;
f2.name = "peach";
f2.price = 4;
f3.name = "apple";
f3.price = 1;
q.push(f1);
q.push(f2);
q.push(f3);
cout << q.top().name << " " << q.top().price << endl;
system("pause");
return 0;
}
输出:
两种比较方式:重载操作符 < 或者自定义比较函数。
注意: priority_queue默认是大根堆的方式,在自定义数据类型的优先级时,如果也想要大根堆,那么就正常地把比较函数写成小于的比较函数,如果想要小根堆,那就写成相反形式。如:
struct cmp{
bool operator() (const fruit &f1, const fruit &f2){
return f1.price > f2.price;
}
};