优先级队列需要包含头文件<queue>,优先级队列的定义如下:
priority_queue<typename, container, functional>
typename是数据的类型;
container是容器类型,可以是vector,queue等用数组实现的容器,不能是list,默认可以用vector;
functional是比较的方式,默认是大顶堆(就是元素值越大,优先级越高);如果使用C++基本数据类型,可以直接使用自带的less和greater这两个仿函数(默认使用的是less,就是构造大顶堆,元素小于当前节点时下沉)。使用自定义的数据类型的时候,可以重写比较函数,也可以进行运算符重载(less重载小于“<”运算符,构造大顶堆;greater重载大于“>”运算符,构造小顶堆)。
运算重载符
对于这串代码:
bool operator()(vector<int>&a,vector<int>&b){
return a[0]<b[0];
}
若比较函数返回
true
:表示第一个参数(a
)的优先级 低于 第二个参数(b
),因此b
会被调整到更靠近堆顶的位置(b
上浮)。若比较函数返回
false
:表示第一个参数(a
)的优先级 高于 第二个参数(b
),因此a
会留在当前位置或上浮到堆顶。
假设依次插入 [5]
, [3]
, [8]
:
插入
[5]
,堆顶为[5]
。插入
[3]
,比较3 < 5
为true
,5
保持堆顶。插入
[8]
,比较8 < 5
为false
,8
上浮到堆顶。
最终堆顶为 [8]
,符合大顶堆特性。
自定义比较函数的5种方式
可以使用现成的 less<T>
来定义大顶堆 greater<T>
来定义小顶堆
从文档出可以看到,传入的可以是 函数指针或者 函数对象(类对操作符()进行了重载,)
方式一:struct重载运算符()(传入函数对象 )
struct cmp{
bool operator()(vector<int>&a,vector<int>&b){
return a[0]>b[0];
}
};
priority_queue<vector<int>,vector<vector<int>>,cmp> q;//小顶堆
方式二:class重载运算符()(传入函数对象 )
class cmp{
public:
bool operator()(vector<int>&a,vector<int>&b){
return a[0]>b[0];
}
};
priority_queue<vector<int>,vector<vector<int>>,cmp> q;//小顶堆
注意:要写在public中
方法三:定义函数(传入函数指针 )
bool cmp(vector<int>&a,vector<int>&b){
return a[0]>b[0];
}
priority_queue<vector<int>,vector<vector<int>>,decltype(&cmp)> q(cmp);//小顶堆
需要通过decltype()
关键字从而推导指针的类型decltype(&cmp)
注意:如果作为类成员函数,一定要声明
static
static bool cmp(vector<int>&a,vector<int>&b){
return a[0]>b[0];
}
方法四:lambda表达式(传入函数指针 )
auto cmp=[](vector<int>&a,vector<int>&b)->bool{
return a[0]>b[0];
};
priority_queue<vector<int>,vector<vector<int>>,decltype(cmp)> q(cmp);//小顶堆
方式五:function包装lambda表达式(传入函数指针)
要加入头文件#include<functional>
function<bool(vector<int>&,vector<int>&)> cmp=[](vector<int>&a,vector<int>&b)->bool{
return a[0]>b[0];
};
priority_queue<vector<int>,vector<vector<int>>,decltype(cmp)> q(cmp);//小顶堆
评论