优先队列 讲解及模板

定义

优先队列(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,cmp1>q1;//小根堆

priority_queue<int,vector,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_queueq1;//小根堆

priority_queueq2;//大根堆

//定义结构体的优先级

struct node
{
int x, y;
friend bool operator < (node a, node b)
{
return a.x>b.x;//结构体中,以x判定优先级
}
};

priority_queueq;


手写堆

能熟练使用系统堆的同时,也应了解如何手写堆

插入操作

优先队列的插入操作与普通队列相似,将新元素插入队尾,只是在插入完成后需要对插入的元素进行“上浮”,即按优先级将其转移到适宜位置

这里以小根堆为例

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() ???

模板

luogu3378

include

include

include

include

include

include

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(opt1) scanf("%d",&x),push(x);
else if(opt
2) printf("%d\n",top());
else pop();
}
return 0;
}

参考来源

百度百科

AC_Gibson的专栏

posted @ 2017-08-14 10:30  XYZinc  阅读(643)  评论(0)    收藏  举报