定义
优先队列(priority queue)
普通的队列是一种先进先出的数据结构,元素在队列尾追加,而从队列头删除。在优先队列中,元素被赋予优先级。当访问元素时,具有最高优先级的元素最先删除。优先队列具有最高级先出 (first in, largest out)的行为特征。
通俗来讲,就是按一定优先顺序弹出元素的队列
时间复杂度为O(logn)
使用
-
优先队列在头文件#include < queue >中
-
声明格式
priority_queue < int > q;//定义一个整形优先队列(默认为大根堆)
priority_queue< int,vector < int >, greater< int > >q;//小根堆
priority_queue< int,vector < int >,less< int > >q;//大根堆
-
基本操作
q.push( );//插入元素
q.pop( );//删除堆顶元素
q.top( );//弹出堆顶元素
q.empty( );//判断队列是否为空
q.size( );//返回队列中元素个数
优先级
在大根堆中,认为数值大的优先级高;小根堆中,认为数值小的优先级高
但有些时候,我们需要自行定义队列元素的优先级,可以使用结构体设置优先级
//方法1
struct cmp1()
{
bool operator() (int &a,int &b)
{
return a>b;//较小值优先级高
}
}
srtuct cmp2()
{
bool operator() (int &a,int &b)
{
return a<b;//较大值优先级高
}
}
priority_queue<int,vector<int>,cmp1>q1;//小根堆
priority_queue<int,vector<int>,cmp2>q2;//大根堆
//方法2
struct node1
{
int x;
bool operator < (const node1 &a) const
{
return x>a.x;//较小值优先级高
}
}
struct node2
{
int x;
bool operator < (const node2 &a) const
{
return x<a.x;//较大值优先级高
}
}
priority_queue<node1>q1;//小根堆
priority_queue<node2>q2;//大根堆
//定义结构体的优先级
struct node
{
int x, y;
friend bool operator < (node a, node b)
{
return a.x>b.x;//结构体中,以x判定优先级
}
};
priority_queue<node>q;
手写堆
能熟练使用系统堆的同时,也应了解如何手写堆
插入操作
优先队列的插入操作与普通队列相似,将新元素插入队尾,只是在插入完成后需要对插入的元素进行“上浮”,即按优先级将其转移到适宜位置
这里以小根堆为例
void push(int x)
{
q[++sz]=x;
int pos=sz;
while(pos>1&&q[pos>>1]>q[pos])//若父节点大于当前节点,交换
swap(q[pos],q[pos>>1]),pos=pos>>1;
}
删除操作
小根堆的本质是一个二叉树,直接删除堆顶即删掉根节点,会导致左右儿子的松散,是不合适的,不妨取出队尾元素,覆盖掉堆顶,再通过上浮操作维护
void pop()
{
int pos=1;
q[pos]=q[sz--];
while(true)
{
int lv=(pos<<1)>sz? inf:q[pos<<1];
int rv=(pos<<1|1)>sz? inf:q[pos<<1|1];
int v=min(lv,rv),nt=lv<rv? (pos<<1):(pos<<1|1);
if(q[pos]>v)
swap(q[pos],q[nt]),pos=nt;
else break;
}
}
其他
int top() {return q[1];}
int size() {return sz;}
bool empty() {return sz==0? true:false;}
void clear() {sz=0;}//系统队列好像不支持清空,只能一个一个pop() ???
模板
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <cmath>
#define inf 2147483646
#define N 1000005
using namespace std;
int q[N],sz,n;
int top() {return q[1];}
void push(int x)
{
q[++sz]=x;
int pos=sz;
while(pos>1&&q[pos>>1]>q[pos])
swap(q[pos],q[pos>>1]),pos=pos>>1;
}
void pop()
{
int rt=q[sz--],pos=1;
q[pos]=rt;
while(true)
{
int lv=(pos<<1)>sz? inf:q[pos<<1];
int rv=(pos<<1|1)>sz? inf:q[pos<<1|1];
int v=min(lv,rv),nt=lv<rv? (pos<<1):(pos<<1|1);
if(q[pos]>v)
swap(q[pos],q[nt]),pos=nt;
else break;
}
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
int opt,x;scanf("%d",&opt);
if(opt==1) scanf("%d",&x),push(x);
else if(opt==2) printf("%d
",top());
else pop();
}
return 0;
}