优先队列:顾名思义,首先它是一个队列,但是它强调了“优先”二字,所以,已经不能算是一般意义上的队列了,它的“优先”意指取队首元素时有一定的选择性,即根据元素的属性选择某一项值最优的出队~
百度百科上这样描述的:
  优先级队列 是不同于先进先出队列的另一种队列。每次从队列中取出的是具有最高优先权的元素
  优先队列的类定义  
  优先队列是0个或多个元素的集合,每个元素都有一个优先权或值,对优先队列执行的操作有1) 查找;2) 插入一个新元素;3) 删除.在最小优先队列(min priorityq u e u e)中,查找操作用来搜索优先权最小的元素,删除操作用来删除该元素;对于最大优先队列(max priority queue),查找操作用来搜索优先权最大的元素,删除操作用来删除该元素.优先权队列中的元素可以有相同的优先权,查找与删除操作可根据任意优先权进行.
优先队列,其构造及具体实现可以先不用深究,现在只需要了解其特性,及在做题中的用法,看过之后会收获不少。
使用优先队列,首先要包函STL头文件  #include <queue>
以一个例子来解释吧(呃,写完才发现,这个代码包函了几乎所有我们要用到的用法,仔细看看吧):

 /*优先队列的基本使用    2010/7/24    dooder*/
#include<stdio.h>
#include<functional>
#include<queue>
#include<vector>
using namespace std;
//定义结构,使用运算符重载,自定义优先级1
struct cmp1{
bool operator ()(int &a,int &b){
return a>b;//最小值优先
}
};
struct cmp2{
bool operator ()(int &a,int &b){
return a<b;//最大值优先
}
};
//定义结构,使用运算符重载,自定义优先级2
struct number1{
int x;
bool operator < (const number1 &a) const {
return x>a.x;//最小值优先
}
};
struct number2{
int x;
bool operator < (const number2 &a) const {
return x<a.x;//最大值优先
}
};
int a[]={,,,,,,,,,,,};
number1 num1[]={,,,,,,,,,,,};
number2 num2[]={,,,,,,,,,,,}; int main()
{ priority_queue<int>que;//采用默认优先级构造队列 priority_queue<int,vector<int>,cmp1>que1;//最小值优先
priority_queue<int,vector<int>,cmp2>que2;//最大值优先 priority_queue<int,vector<int>,greater<int> >que3;//注意“>>”会被认为错误,
//这是右移运算符,所以这里用空格号隔开
priority_queue<int,vector<int>,less<int> >que4;////最大值优先 priority_queue<number1>que5;
priority_queue<number2>que6; int i;
for(i=;a[i];i++){
que.push(a[i]);
que1.push(a[i]);
que2.push(a[i]);
que3.push(a[i]);
que4.push(a[i]);
}
for(i=;num1[i].x;i++)
que5.push(num1[i]);
for(i=;num2[i].x;i++)
que6.push(num2[i]); printf("采用默认优先关系:\n(priority_queue<int>que;)\n");
printf("Queue 0:\n");
while(!que.empty()){
printf("%3d",que.top());
que.pop();
}
puts("");
puts(""); printf("采用结构体自定义优先级方式一:\n(priority_queue<int,vector<int>,cmp>que;)\n");
printf("Queue 1:\n");
while(!que1.empty()){
printf("%3d",que1.top());
que1.pop();
}
puts("");
printf("Queue 2:\n");
while(!que2.empty()){
printf("%3d",que2.top());
que2.pop();
}
puts("");
puts("");
printf("采用头文件\"functional\"内定义优先级:\n(priority_queue<int,vector<int>,greater<int>/less<int> >que;)\n");
printf("Queue 3:\n");
while(!que3.empty()){
printf("%3d",que3.top());
que3.pop();
}
puts("");
printf("Queue 4:\n");
while(!que4.empty()){
printf("%3d",que4.top());
que4.pop();
}
puts("");
puts("");
printf("采用结构体自定义优先级方式二:\n(priority_queue<number>que)\n");
printf("Queue 5:\n");
while(!que5.empty()){
printf("%3d",que5.top());
que5.pop();
}
puts("");
printf("Queue 6:\n");
while(!que6.empty()){
printf("%3d",que6.top());
que6.pop();
}
puts("");
return ;
}
/*
运行结果 :
采用默认优先关系:
(priority_queue<int>que;)
Queue 0:
91 83 72 56 47 36 22 14 10 7 3 采用结构体自定义优先级方式一:
(priority_queue<int,vector<int>,cmp>que;)
Queue 1:
3 7 10 14 22 36 47 56 72 83 91
Queue 2:
91 83 72 56 47 36 22 14 10 7 3 采用头文件"functional"内定义优先级:
(priority_queue<int,vector<int>,greater<int>/less<int> >que;)
Queue 3:
3 7 10 14 22 36 47 56 72 83 91
Queue 4:
91 83 72 56 47 36 22 14 10 7 3 采用结构体自定义优先级方式二:
(priority_queue<number>que)
Queue 5:
3 7 10 14 22 36 47 56 72 83 91
Queue 6:
91 83 72 56 47 36 22 14 10 7 3
*/

好了,如果你仔细看完了上面的代码,那么你就可以基本使用优先队列了,下面给出一些我做题中有过的一些应用,希望能给大家带来一些启
示~

下面给出本文出处:http://www.cnblogs.com/heqinghui/archive/2013/07/30/3225407.html

附原作者部分代码↓↓↓

1、先来一个我们最近做的题吧,http://acm.hdu.edu.cn/showproblem.php?pid=1242
题意:某人被关在囚笼里等待朋友解救,问能否解救成功,最少需要多少时间~
具体:可同时有几个朋友,每走一格消耗一分钟的时间 ,地图上还存在着卫兵,卫兵可以解决掉,但是要另外花费一分钟~
分析:从“a”出发,此题可以用回溯法进行深搜,但那样做的话,效率还是不能让人满意,但是广搜的话,由于入队后每次出队时,根据地
图情况的不同,出队元素所记忆的时间并不是层次递增的,因此使用简单广搜的话,同样需要全部搜索才能找到正确答案。有没有一种方法能
让某一步因为遇到士兵而多花时间的结点在队列中向后推迟一层出队呢?答案是肯定的,在这里我们可以用优先队列来实现,总体思想上是,
根据时间进行优先性选择,每次都要出队当前队列元素中记录时间最少的出队,而入队处理时,我们可以按顺序对四个方向上的各种情况按正
常处理入队就行了,出队顺序由优先队列根据预设优先性自动控制。这样,我们就可以从“a”进行基于优先队列的范围搜索了,并且在第一
次抵达有朋友的位置时得到正确结果~具体实现代码:

 /*HDU 1242  基于优先队列的范围搜索,16ms   dooder*/  

 #include<stdio.h>
#include<queue>
using namespace std; #define M 201
typedef struct p{
int x,y,t;
bool operator < (const p &a)const
{
return t>a.t;//取时间最少优先
}
}Point; char map[M][M];
Point start;
int n,m;
int dir[][]={{,},{-,},{,},{,-}}; int bfs()
{
priority_queue<Point>que;
Point cur,next;
int i; map[start.x][start.y]='#';
que.push(start);
while(!que.empty()){
cur=que.top();//由优先队列自动完成出队时间最少的元素
que.pop();
for(i=;i<;i++){
next.x=cur.x+dir[i][];
next.y=cur.y+dir[i][];
next.t=cur.t+;
if(next.x<||next.x>=n||next.y<||next.y>=m)
continue;
if(map[next.x][next.y]=='#')
continue;
if(map[next.x][next.y]=='r')
return next.t;
if(map[next.x][next.y]=='.'){
map[next.x][next.y]='#';
que.push(next);
}
else if(map[next.x][next.y]=='x'){
map[next.x][next.y]='#';
next.t++;
que.push(next);
}
}
}
return -;
}
int main()
{
int i,ans;
char *p;
while(scanf("%d%d",&n,&m)!=-){
for(i=;i<n;i++){
scanf("%s",map[i]);
if(p=strchr(map[i],'a')){
start.x=i;
start.y=p-map[i];
start.t=;
}
}
ans=bfs();
printf(ans+?"%d\n":"Poor ANGEL has to stay in the prison all his life.\n",ans);
}
return ;
}

2、http://acm.hdu.edu.cn/showproblem.php?pid=1053
题意:给出一行字符串,求出其原编码需要的编码长度和哈夫曼编码所需的长度,并求其比值
分析:根据哈夫曼生成树的生成过程可知,其生成树的权值是固定的而且这个值是最小的,而且其值根据生成树的顺序,我们可以找出规律而
不需要真的去生成一棵树然后再求出权值,其模拟过程为取出队列中权值最小的两个元素,将其值加入结果中,然后将这两个元素的权值求和
即得出其父节点的权值,将生成元素作为结点入队~~如此循环,直至取出队列中最后两个元素加入结果,实现代码如下:

 /*HDU 1053  采用广搜求哈夫曼生成树的权值 0ms   dooder*/
#include<stdio.h>
#include<string.h>
#include<ctype.h>
#include<functional>
#include<queue>
using namespace std;
#define M 1000050
char str[M];
int list[]; priority_queue< int,vector<int>,greater<int> >que; int main()
{
int ans,sum;
int i,a,b,c;
while(scanf("%s",str),strcmp(str,"END")){
memset(list,,sizeof(list));
for(i=;str[i];i++){
if(isalpha(str[i]))
list[str[i]-'A']++;
else
list[]++;
}
sum=i*;ans=i;c=;
for(i=;i<;i++){
if(list[i]){
que.push(list[i]);
c++;
}
}
if(c>){ans=;//注意只有一种字符的情况
while(que.size()!=){
a=que.top();
que.pop();
b=que.top();
que.pop();
ans+=a+b;
que.push(a+b);
}
while(!que.empty())//使用后清空队列
que.pop();
}
printf("%d %d %.1f\n",sum,ans,1.0*sum/ans);
}
return ;
}

3、http://acm.pku.edu.cn/JudgeOnline/problem?id=2263
这是第二次练习赛时,我们做过的最后一题,这里采用优先队列进行实现,在《谁说不能这样做题》中已提到这种方法,在这里再次放出代
码,~
题意:给出各城市间道路的限制载重量,求出从一个城市到另外一个城市的贷车能够运载的最大货物重量。
分析:采用优先队列,每次取出当前队列中结点的minheavy最大值出队,对它的连接结点搜索入队,这样,从出发点开始就可以
在到达终点时求出结果,即最大载货物重,实现代码如下:

 /*POJ 2263  16ms  dooder*/  

 #include<stdio.h>
#include<string.h>
#include<queue>
using namespace std;
#define M 201
typedef struct w{
int city;
int mintons;
bool operator < (const w &a)const {
return mintons < a.mintons;
}//优先性定义
}Way;
char citys[M][];
int map[M][M];
bool mark[M][M];
int n,m,from,to,ans,k;
priority_queue <Way> que;
int min(int a,int b)
{
return a>b?b:a;
}
void bfs()
{
Way cur,next;
int i;
while(!que.empty()){
cur=que.top();
que.pop();
if(cur.city==to){
if(cur.mintons>ans)
ans=cur.mintons;
while(!que.empty())
que.pop();
return ;
}
for(i=;i<n;i++){
if(map[cur.city][i]&&!mark[cur.city][i]){
next.city=i;
next.mintons=min(cur.mintons,map[cur.city][i]); mark[cur.city][i]=mark[i][cur.city]=;
que.push(next);
}
}
}
}
void run()
{
int i,temp,index;
Way cur;
ans=;
memset(mark,,sizeof(mark));
temp=;
for(i=;i<n;i++){
if(map[from][i]>temp){
temp=map[from][i];
index=i;
}
}
cur.city=index;
cur.mintons=temp;
que.push(cur);
bfs();
}
int main()
{
int k1,k2,tons,t=;
char s1[],s2[];
while(scanf("%d%d",&n,&m),n||m){
k=;
while(m--){
scanf("%s%s%d",s1,s2,&tons);
for(k1=;strcmp(s1,citys[k1])&&k1<k;k1++);
if(k1==k)
strcpy(citys[k++],s1);
for(k2=;strcmp(s2,citys[k2])&&k2<k;k2++);
if(k2==k)
strcpy(citys[k++],s2);
map[k1][k2]=map[k2][k1]=tons;
}
scanf("%s%s",s1,s2);
for(from=;strcmp(citys[from],s1);from++);
for(to=;strcmp(citys[to],s2);to++);
run();
printf("Scenario #%d\n",t++);
printf("%d tons\n\n",ans);
}
return ;
}

当然了,优先队列的用法决不是仅仅提到的这些,各种应用还需要大家去发现,给道题大家可以练习一下hdu 2066\
相信大家已经学到不少了,还有一点可以告诉大家,优先队列是启发式搜索的数据结构基础,希望好好理解,并逐步掌握其用法~
加:失策啊,竟然忘了说优先队列的效率了,其时间复杂度为O(logn).n为队列中元素的个数,存取都需要消耗时间~

优先队列详解priority_queue .RP的更多相关文章

  1. 如约而至,Java 10 正式发布! Spring+SpringMVC+MyBatis+easyUI整合进阶篇(十四)Redis缓存正确的使用姿势 努力的孩子运气不会太差,跌宕的人生定当更加精彩 优先队列详解(转载)

    如约而至,Java 10 正式发布!   3 月 20 日,Oracle 宣布 Java 10 正式发布. 官方已提供下载:http://www.oracle.com/technetwork/java ...

  2. c++ STL - priority_queue优先队列详解

    简述 普通的队列是一种先进先出的数据结构,元素在队列尾追加,而从队列头删除.在优先队列中,元素被赋予优先级.当访问元素时,具有最高优先级的元素最先删除.优先队列具有最高级先出 (first in, l ...

  3. C++ STL 优先队列详解

    一.解释: 优先队列是队列的一种,不过它可以按照自定义的一种方式(数据的优先级)来对队列中的数据进行动态的排序,每次的push和pop操作,队列都会动态的调整,以达到我们预期的方式来存储. 例如,将元 ...

  4. STL 优先队列详解

    优先队列是一个保证队列里元素单调的队列,我们可以利用它来维护一个线性结构的单调性. 一般的优先队列: 当然需要加头文件 #include <queue> priority_queue &l ...

  5. C++优先队列详解

    转自csdn的文章,仅作为学习笔记.原文链接:https://blog.csdn.net/weixin_36888577/article/details/79937886 普通的队列是一种先进先出的数 ...

  6. 【Java基础】JAVA中优先队列详解

    总体介绍 优先队列的作用是能保证每次取出的元素都是队列中权值最小的(Java的优先队列每次取最小元素,C++的优先队列每次取最大元素).这里牵涉到了大小关系,元素大小的评判可以通过元素本身的自然顺序( ...

  7. STL priority_queue 常见用法详解

    <算法笔记>学习笔记 priority_queue 常见用法详解 //priority_queue又称优先队列,其底层时用堆来实现的. //在优先队列中,队首元素一定是当前队列中优先级最高 ...

  8. 【STL】优先队列priority_queue详解+OpenJudge-4980拯救行动

    一.关于优先队列 队列(queue)这种东西广大OIer应该都不陌生,或者说,队列都不会你还学个卵啊(╯‵□′)╯︵┻━┻咳咳,通俗讲,队列是一种只允许从前端(队头)删除元素.从后端(队尾)插入元素的 ...

  9. 详解C++ STL priority_queue 容器

    详解C++ STL priority_queue 容器 本篇随笔简单介绍一下\(C++STL\)中\(priority_queue\)容器的使用方法和常见的使用技巧. priority_queue容器 ...

随机推荐

  1. Codeforces Round #263 (Div. 2)C(贪心,联想到huffman算法)

    数学家伯利亚在<怎样解题>里说过的解题步骤第二步就是迅速想到与该题有关的原型题.(积累的重要性!) 对于这道题,可以发现其实和huffman算法的思想很相似(可能出题人就是照着改编的).当 ...

  2. 3.20 内存及效率的一些总结 3.21 设置竖屏 3.22 CCLOG与CCLog区别

    3.20 内存及效率的一些总结 3.21 设置竖屏 1.android AndroidManifest.xml文件中, screenOrientation="landscape" ...

  3. CANopenSocket CANopenCommand.c hacking

    /***************************************************************************** * CANopenSocket CANop ...

  4. 使用open_read_write等底层函数来赋值一个文件

    /* * 该程序是练习read(),write(),open(),create(),close(),lseek()等函数. *  * 该程序的处理思路: *  1: 在程序所在的目录去打开一个文件,如 ...

  5. C#进阶之路(五):Linq初识

    关于LINQ的文章,网上有很多,所以这篇文章我主要是总结下我自己的学习心得. 首先需要先了解的相关技术 1.隐式类型.匿名类型.对象初始化器 1)隐式类型,使用var关键字创建,C#编译器会根据用于初 ...

  6. [ZOJ2587]Unique Attack

    vjudge sol 最小割判定唯一性. 只要做完一个任意最小割后,判断一下是不是所有点都要么和\(S\)相连,要么和\(T\)相连. 只要两边各一次\(dfs\)就行了. code #include ...

  7. LeetCode 480. Sliding Window Median

    原题链接在这里:https://leetcode.com/problems/sliding-window-median/?tab=Description 题目: Median is the middl ...

  8. h5废弃的标签和属性及新增的标签和属性

    一.废弃的标签和属性 1.表现性元素 a) basefont b) big c) center d) font e) strike f) tt 2.框架类元素 a) frame b) frameset ...

  9. python 编码拓展,小数据池,

    编码拓展: 1.在所有类型的编码中,编码的二进制互不识别, 2.在传输的过程中不能是万国码的二进制解码传输, 因此将unicode变为utf - 8或者变成gbk编码尤为重要; 利用encode编码为 ...

  10. python 修改文件内容

    python 修改文件内容 一.修改原文件方式 1 def alter(file,old_str,new_str): 2 """ 3 替换文件中的字符串 4 :param ...