提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
文章目录
priority_queue的了解
1.priority_queue称为优先级队列底层是用vector容器来作为储存数据,在vector的基础上用堆的算法来储存元素。所以说priority_queue就是一个堆,有任何用到堆的地方都可以优先使用priority_queue
优先级队列是什么意思呢,也就是说插入的元素默认按照从大到小的元素排列的,也就是大堆。
priority_queue的定义方式
方式一:指定底层容器和堆结构
1.priority_queue<int,vector<int>,less<int>>q1
2.priority_queue<int,vector<int>,greater<int>>q2;
方式二:不指定底层容器和堆结构(默认使用vector容器,和大堆结构)
priority_queue<int>q;
priority_queue 的各个接口
示例:
#include<iostream>
#include<functional>
#include<queue>
using namespace std;
int main()
{
priority_queue<int> q1;
q.push(1);
q.push(2);
q.push(3);
q.push(4);
q.push(5);
while(!q.empty())
{
cout<<q.top()<<" ";
q.pop();
}
cout<<endl;//5 4 3 2 1
return 0;
}
priority_queue的模拟实现
在实现priority_queue之前,我们先了解一下堆的两个重要算法:
堆的向上调整算法
总的来说:就是插入一个结点,跟父节点进行比较,如果大就swap。
向上调整代码:
//向上调整算法 //这里是大堆示例
void AdjustUp(int *a,int child)
{
//求parent的位置
int parent = (child - 1) / 2;
while (child>0)
{
if (a[child] > a[parent])//如果孩子比父母大就交换
{
std::swap(a[child],a[parent]);
child = parent;
parent = (child - 1) / 2;
}
//已经成堆
else
{
break;
}
}
}
堆的向下调整算法
注意:向下调整算法,如果是建立小堆,那么根的左右子树必须是小堆,反之大堆
上图是符合条件的,60 的左右子树都是大堆,所以我们从根节点向下面进行调整
向下调整代码:(以大堆示例)
template<class T>
void AdjustDown(T& a ,int size,int parent)
{
int child=parent*2+1;//默认孩子是左孩子
while(child<size)
{
//判断右孩子
if(child+1<size && a[child+1]>a[child])
{
child++;//换成右孩子
}
if(a[child]>a[parent])//孩子比根节点大,交换
{
std::swap(a[child],a[parent]);
parent=child;
child=parent*2+1;
}
else //以成堆
break;
}
priority_queue 模拟实现代码:
#pragma once
#include<iostream>
using namespace std;
#include<vector>
namespace pri_que //防止命名空间冲突
{
//比较方式 (内部默认是使用大堆)
template<class T>
struct less
{
bool operator()(const T& x, const T& y)
{
return x < y;
}
};
//小堆
template<class T>
struct greater
{
bool operator()(const T& x, const T& y)
{
return x > y;
}
};
template<class T,class Container=vector<T>,class Compare = less<T>>
class priority_queue
{
public:
//向上调整算法
void AdjustUp(int child)
{
int parent = (child - 1) / 2;
while (child > 0)
{
if (a[parent] < a[child])
{
std::swap(a[parent], a[child]);
child = parent;
parent = (child - 1) / 2;
}
else
break;
}
}
//向下调整算法
void AdjustDown(int size, int parent)
{
int child = parent * 2 + 1;//默认左孩子
while (child < size)
{
if (child + 1 < size && _con[child + 1] > _con[child])
child++;//变成右孩子
if (a[parent] < a[child])
{
std::swap(a[parent], a[child]);
parent = child;
child = parent * 2 + 1;
}
else
break;
}
}
//插入元素到队尾(并且排序)
void push(const T& x)
{
_con.push_back(x);
AdjustUp(_con.size() - 1);//向上调整
}
//出队 队头 --- 先将队头和队尾数据交换,再出队
void pop()
{
std::swap(_con[0], _con[_con.size() - 1];
_con.pop_back();
AdjustDown(_con.size(),0)//从第0个数据向下调整
}
//访问队头元素
T& top()
{
return _con[0];
}
const T& top()const
{
return _con[0];
}
//获取队列有效元素个数
size_t size()const
{
return _con.size();
}
//判断队列是否为空
bool empty()const
{
return _con.empty();
}
private:
Container _con;//底层容器
Compare_comp;//比较方式
};
}
如有错误,多多指教!