cplusplus官网 : priority_queue的说明
优先级队列和普通的队列不是一个概念,普通的queue遵守先进先出的规则,而优先级队列遵守优先级最高的先出,本质上就是堆排
我们给上一组数据,调用top函数进行打印输出发现最大值优先输出,默认降序
如果要排成升序呢?
官网提供了模版参数,我们发现这里传的不是类型而是对象,如果要排升序通过传greater,默认是less
我们在实现前需要注意,模版是不支持分离编译的,因此我们在hpp里面进行声明和定义
首先默认创建一个大堆,这里就不再赘述概念,可以参考下面的链接
堆排详细说明
//大堆
template<class T, class Container = vector<T>, class Compare = Less<T> >
class priority_queue{
public:
void push(const T& x){
_con.push_back(x);
AdjustUp(_con.size() - 1); //向上调整保持大堆状态
}
void pop(){
swap(_con[0], _con[_con.size()-1]); //头尾交换,向下调整
_con.pop_back();
AdjustDown(0);
}
private:
Container _con;
}
下面是向上和向下调整函数实现,注意默认的是Less类模版
void AdjustUp(size_t child){
size_t parent = (child-1)/2;
while(child > 0){
if(_con[child] > _con[parent]){
swap((_con[child] > _con[parent]);
child = parent;
parent = (child-1)/2;
}else{
break;
}
}
}
void AdjustDown(size_t parent){
int child = parent*2 + 1;
while(child < _con.size()){
if(child < _con.size() && _con[child] < _con[child+1] ){
child++;
}
if(_con[parent] < _con[child]){
swap(_con[parent], _con[child] );
parent = child;
child = parent * 2 + 1;
}else{
break;
}
}
}
这里在构造函数的时候就需要建堆了
//默认构造,不用写什么,会自动调用构造函数
priority_queue(){}
//带参构造
template<class InputIterator>
priority_queue(InputIterator first, InputIterator last){
//数据插入
while(first != last){
_con.push_back(*first);
++first;
}
//建堆
for(int i= (_con.size()-1-1) / 2 ; i >= 0; --i){ // size()-1 是最后一个数据的下标,父亲的话再-1 ,除2
AdjustDown(i);
}
}
最后我们考虑一个问题:
解决完大堆的实现后,如果在不修改符号的情况下变小堆呢?
所以就有了仿函数的概念
//仿函数/函数对象,可以像函数一样去使用
//建大堆,排升序
class Less{
public:
bool operator()(const T& x, const T& y){
return x < y;
}
};
//建小堆,排降序
template<class T>
class Greater{
public:
bool operator()(const T& x, const T& y){
return x > y;
}
};
Gitee链接
priority_queue simulation
创作不易,如果文章对你帮助的话,点赞三连哦:)