priority_queue(优先队列)允许用户为队列中元素设置优先级,放置元素的时候不是直接放到队尾,而是放置到比它优先级低的元素前面。
priority_queue有三个模板参数:priority_queue
Type :为数据类型,
Container: 为保存数据的容器,必须是用数组实现的容器,比如vector,deque等等,但不能用 list。STL里面默认用的是vector。
Functional :为元素比较方式。基本数据类型或已定义了比较运算符的类,可以直接用STL的less算子和greater算子——默认使用less算子,即小的往后排,大的往前排,大的先出队(出队时,序列顶的最大的元素出队)。
对于greater 算子大的往后排,小的往前排,小的先出队(出队时,序列顶的最小的元素出队)。
示例代码如下:
priority_queue
priority_queue
priority_queue
empty() 如果队列为空返回真
pop() 删除队顶元素
push() 加入一个元素
size() 返回优先队列中拥有的元素个数
top() 返回优先队列队顶元素(队列中的front()变成了top())
在默认的优先队列中,优先级高的先出队。在默认的int型中先出队的为较大的数。
注意:priority queue和 queue不同的是,priority queue没有j back() 和 front() ,而只能通过top()或pop() ,访问队尾元素(也称堆顶元素),也就是优先级最高的元素。
#include
using namespace std;
int main ()
{ priority_queue q;
q.push(1);
q.push(5);
q.push(3);
q.push(9);
q.push(2);
cout<
结果为:
#include
using namespace std;
int main ()
{ priority_queue,greater > q;
q.push(1);
q.push(5);
q.push(3);
q.push(9);
q.push(2);
cout<
结果为:
#include
using namespace std;
int main()
{ priority_queue a; //优先级队列默认是使用vector作容器。
int i;
for (i=0; i<10; i++) //压入数据
a.push(rand());
printf("%d\n", a.size()); //优先级队列的大小
while (!a.empty()) //取优先级队列数据并将数据移出队列
{ printf("%d ", a.top());
a.pop();
}
putchar('\n');
return 0;
}
使用priority_queue时,最困难的可能就是如何定义比较算子了。
可以有多种方法,最常见的就是重载比较运算符,注意重载操作返回的结果是bool类型,并且此处的比较操作与map等其他处不同,在map中以<作为比较操作,则值小的排在前面,而优先级队列中以<作为比较操作,值大的优先级高,而优先级高的放在队列前面,反之以>操作符确定优先级关系时,表明优先级是按值从大到小排列,值小的优先级高,优先级高的放在队列前面。
自定义优先级的三种方法:
1.重载操作符:
bool operator < (const node &a, const node &b)
{
return a.value < b.value; // 按照value从大到小排列
}
priority_queueq;
(const node &a是用引用传递,比按值传递node a效率更高,效果是一样的).
下面这个例子是重载比较运算符,在priority_queue中插入若干个结构体,结构体成员为(x,y,z),以结构体成员z值来确定优先级顺序,z值大的排在队列前面:
#include
using namespace std;
struct T
{ int x,y,z;
}a;
bool operator<(const T &t1,const T &t2)
{ return t1.z'按照z从小到大排列,'<'按照z从大到小排列
}
int main()
{ priority_queueq;
for(int i=1;i<=4;i++)
{ cin>>a.x>>a.y>>a.z;
q.push(a);
}
while(!q.empty())
{ T t=q.top();
q.pop();
cout<
输入:
4 4 3 2 2 5 1 5 4 3 3 6
输出:
2.比较函数声明方式:
struct cmp{
bool operator ()(const node &a, const node &b)
{
return a.value>b.value;// 按照value从小到大排列
}
};
priority_queue, cmp>q;
下面这个例子是自定义比较函数,在priority_queue中插入若干个结构体,结构体成员为(x,y,z),以结构体成员z值来确定优先级顺序:
#include
using namespace std;
struct T
{ int x,y,z;
}a;
struct cmp
{ bool operator ()(const T &a, const T &b)
{ return a.z>b.z;// '>'按照z从小到大排列,'<'按照z从大到小排列
}
};
priority_queue, cmp>q;
int main()
{ for(int i=1;i<=4;i++)
{ cin>>a.x>>a.y>>a.z;
q.push(a);
}
while(!q.empty())
{ T t=q.top();
q.pop();
cout<
输入:
4 4 3 2 2 5 1 5 4 3 3 6
输出:
3.结构体声明方式:
struct node{
int value;
friend bool operator<(const node &a,const node &b){
return a.valueq;
下面这个例子是结构体声明方式,在priority_queue中插入若干个结构体,结构体成员为(x,y,z),以结构体成员z值来确定优先级顺序:
#include
using namespace std;
struct T{
int x,y,z;
friend bool operator<(const T &a,const T &b){
return a.z'按照z从小到大排列,'<'按照z从大到小排列
}
}a;
priority_queueq;
int main()
{ for(int i=1;i<=4;i++)
{ cin>>a.x>>a.y>>a.z;
q.push(a);
}
while(!q.empty())
{ T t=q.top();
q.pop();
cout<
输入:
4 4 3 2 2 5 1 5 4 3 3 6
输出:
1、 有序表的最小和
【问题描述】
给出两个长度为 n 的有序表 A 和 B,在 A 和 B 中各任取一个元素,可以得到 n 2 个和,求这些和中最小的 n 个。
【输入格式】
第 1 行包含 1 个整数正 n(n≤400000)。
第 2 行与第 3 行分别有 n 个整数,各代表有序表 A 和 B。一行中的每两个整数之间用一个空格隔开,大小在长整型范围内,数据保证有序表单调递增。
【输出格式】
输出共 n 行,每行一个整数,第 i 行为第 i 小的和。
数据保证在 long long 范围内。
【输入样例】
3
1 2 5
2 4 7
【输出样例】
3
4
5
2、合并果子
题目描述
在一个果园里,多多已经将所有的果子打了下来,而且按果子的不同种类分成了不同的堆。多多决定把所有的果子合成一堆。每一次合并,多多可以把两堆果子合并到一起,消耗的体力等于两堆果子的重量之和。可以看出,所有的果子经过 n−1 次合并之后, 就只剩下一堆了。多多在合并果子时总共消耗的体力等于每次合并所耗体力之和。因为还要花大力气把这些果子搬回家,所以多多在合并果子时要尽可能地节省体力。假定每个果子重量都为 1 ,并且已知果子的种类 数和每种果子的数目,你的任务是设计出合并的次序方案,使多多耗费的体力最少,并输出这个最小的体力耗费值。
例如有 33 种果子,数目依次为 1, 2, 9。可以先将 1 、 2堆合并,新堆数目为 3 ,耗费体力为 3 。接着,将新堆与原先的第三堆合并,又得到新的堆,数目为 12 ,耗费体力为 12 。所以多多总共耗费体力 =3+12=15 。可以证明 15 为最小的体力耗费值。
输入输出格式
输入格式:
共两行。
第一行是一个整数 n(1≤n≤10000) ,表示果子的种类数。
第二行包含 n 个整数,用空格分隔,第 i 个整数ai(1≤ai≤20000) 是第 i 种果子的数目。
输出格式:
一个整数,也就是最小的体力耗费值。输入数据保证这个值小于 2^31 。
输入输出样例
输入样例#1:
3
1 2 9
输出样例#1:
15
说明
对于30%的数据,保证有n≤1000:
对于50%的数据,保证有n≤5000;
对于全部的数据,保证有n≤10000
3、priority queue练习
总时间限制: 2500ms 内存限制: 131072kB
描述
我们定义一个正整数a比正整数b优先的含义是:
*a的质因数数目(不包括自身)比b的质因数数目多;
*当两者质因数数目相等时,数值较大者优先级高。
现在给定一个容器,初始元素数目为0,之后每次往里面添加10个元素,每次添加之后,要求输出优先级最高与最低的元素,并把该两元素从容器中删除。
输入
第一行: num (添加元素次数,num <= 30)
下面10*num行,每行一个正整数n(n < 10000000).
输出
每次输入10个整数后,输出容器中优先级最高与最低的元素,两者用空格间隔。
样例输入
1
10 7 66 4 5 30 91 100 8 9
样例输出
66 5
4、看病要排队
看病要排队这个是地球人都知道的常识。
不过经过细心的0068的观察,他发现了医院里排队还是有讲究的。0068所去的医院有三个医生(汗,这么少)同时看病。而看病的人病情有轻重,所以不能根据简单的先来先服务的原则。所以医院对每种病情规定了10种不同的优先级。级别为10的优先权最高,级别为1的优先权最低。医生在看病时,则会在他的队伍里面选择一个优先权最高的人进行诊治。如果遇到两个优先权一样的病人的话,则选择最早来排队的病人。
现在就请你帮助医院模拟这个看病过程。
Input
输入数据包含多组测试,请处理到文件结束。 Output 对于每个"OUT A"事件,请在一行里面输出被诊治人的编号ID。如果该事件时无病人需要诊治,则输出"EMPTY"。 Sample Input Sample Output 思路:简单的模拟,或者直接用优先队列,因为病人的级别越高就有更高的优先权,所以用优先队列更容易理解; 代码:模拟 思路:将每个病人的信息储存为一个结构体,将每个医生的求诊信息当成队列数组中的元素。以病人的级别,若级别相同,则以病人来到医院的先后作为队列的优先级。 代码:优先队列
每组数据第一行有一个正整数N(0
一共有两种事件:
1:"IN A B",表示有一个拥有优先级B的病人要求医生A诊治。(0 2:"OUT A",表示医生A进行了一次诊治,诊治完毕后,病人出院。(0
诊治人的编号ID的定义为:在一组测试中,"IN A B"事件发生第K次时,进来的病人ID即为K。从1开始编号。 7
IN 1 1
IN 1 2
OUT 1
OUT 2
IN 2 1
OUT 2
OUT 1
2
IN 1 1
OUT 1
2
EMPTY
3
1
#include
#include