队列,优先队列
queue俗称队列,是STL中常用的容器之一,使用时需要引用头文件#include<queue>
他与栈十分相似,可以说是一个两端开口的栈,每次都可以向队尾插入元素,从队头删除一个元素。
1.定义queue:
queue<int>q1;
queue<double>q2;
queue<char>q3;
2.常用函数:
push() 在队尾插入一个元素
pop() 删除队列第一个元素
size() 返回队列中元素个数
empty() 如果队列空则返回true
front() 返回队列中的第一个元素
back() 返回队列中最后一个元素
来一道简单的队列模板题
Throwing cards away I
给出的是一副有序的n张牌,编号为1至n,牌1在上,牌n在下。只要这副牌中至少有两张牌,就可以进行以下操作。
扔掉最上面的一张牌 然后把现在在最上面的那张牌移到最下面去.
你的任务是找到被丢弃的牌和最后一张剩余的牌的顺序。
每一行输入(除了最后一行)都包含一个数字n≤50。最后一行包含0,这一行不应该被处理。对于输入的每个数字产生两行输出。第一行显示被丢弃的牌的序列,第二行报告最后剩下的牌。任何一行都不会有前导或尾部的空格。参见示例中的预期格式。
Sample input
7
19
10
6
0
Output
Discarded cards: 1, 3, 5, 7, 4, 2
Remaining card: 6
Discarded cards: 1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 4, 8, 12, 16, 2, 10, 18, 14
Remaining card: 6
Discarded cards: 1, 3, 5, 7, 9, 2, 6, 10, 8
Remaining card: 4
Discarded cards: 1, 3, 5, 2, 6
Remaining card: 4
题目要求很简单给出1-n张牌利用queue进行模拟输出即可(这里我是手写了一个数组q来模拟队列)
#include<iostream>
#include<cstring>
using namespace std;
int n;
int main() {
while (~scanf("%d", &n)) {
int q[1000];
int a[1000];
if (n == 0)break;
for (int i = 1; i <= n; i++)q[i] = i;
int hh = 1, tt = n; int m = 1;
while (hh < tt) {
a[m++] = q[hh];
hh++;
q[++tt] = q[hh++];
}
if(n!=1)
printf("Discarded cards: ");
else {
printf("Discarded cards:\n");
printf("Remaining card: 1\n");
continue;
}
for (int i = 1; i < m; i++)
{
if (i != m - 1)
printf("%d, ", a[i]);
else
printf("%d\n", a[i]);
}
printf("Remaining card: %d\n", q[hh]);
}
}
再来看一下他的孪生同胞priority_queue同样也是要使用#include<queue>
,虽然名字看起来都有队列俩字,但是优先队列和队列的结构大不相同,优先队列是一个堆,默认为大根堆(树根为最大的数),是一个树状结构。
模板申明带3个参数:priority_queue<Type, Container, Functional>,其中Type 为数据类型,Container为保存数据的容器,Functional 为元素比较方式。
Container必须是用数组实现的容器,比如vector,deque等等,但不能用 list。STL里面默认用的vector。
1.定义
priority_queue<int> q;/一般定义
priority_queue<struct a> q;/与结构体结合的定义
priority_queue<pair<int,int> > coll;/结合pair内部按pair的first元素降序,first相同再按second元素降序。
priority_queue<int, vector<int>, greater<int> > q;/小根堆的定义方式需要引用第三个参数
priority_queue<pair<int,int>,vector<pair<int,int> >,greater<pair<int,int> > > coll;
/先按照pair的first元素升序,first元素相等时,再按照second元素升序
来道题来看看运用时出现的问题吧
先来翻译一下巨长的题干0.0
题目描述
一个数据流是一个实时,连续,有序的条目序列。一些实例包括传感器数据,互联网贸易,金融报价,网上拍卖,交易日志,Web使用日志和电话呼叫记录。同样,在数据流上的查询每隔一定时间就要连续运行,在产生新的数据的时候就要产生新的结果。例如,一家工厂的仓库的温度检测系统可以执行如下的查询:
查询- 1:“每五分钟,检索在过去5分钟内的最高温度。”
查询- 2:“返回在过去10分钟各个楼层的平均气温。”
我们开发了一个名为Argus的数据流管理系统,以处理在数据流上的查询。用户可以在Argus上登记查询。 Argus将在不断变化的数据上持续执行查询,并以要求的频率向相应的用户返回结果。
对Argus,我们以下述的指令来登记查询:
Register Q_num Period
Q_num (0 < Q_num <= 3000)是查询的ID编号,Period (0 < Period <= 3000)是两个连续的查询结果返回之间的时间间隔。在登记了Period秒之后,首次返回结果,此后,每隔Period秒返回结果。
在Argus上登记了几个不同的查询,所有的查询都有不同的Q_num。你的任务是给出前K个返回结果的查询。如果两个或多个查询同时返回结果,则将他们按照Q_num的升序进行排列。
输入
输入的第一部分是在Argus上登记的指令,一条指令占一行,假定指令的编号不超过1000,并且所有的指令同时开始执行。这一部分的结束用“#”表示。
第二部分是你的工作,只有一行,给出一个正整数K (<= 10000)。
输出
输出前K个返回结果的查询的Q_num,每个数字一行。
样例输入
Register 2004 200
Register 2005 300
5
样例输出
2004
2005
2004
2004
2005
思路很简单啊,给一个标号一个时间,每过这个时间一次输出标号,优先输出较小的标号。
但是在写代码的时候我用到了结构体,碰到了很多麻烦。(小蒻蒟第一次)
#include<iostream>
#include<algorithm>
#include<queue>
using namespace std;
struct re {
int num, sec;
bool operator<(const re& c) const //重载运算符
{
return sec > c.sec || (sec == c.sec && num > c.num); //时间从小到大排序,相同的标号小的优先
}
};
priority_queue<struct re>s;
int main() {
while (1) {
string op;
op.clear();
cin >> op;
if (op == "#")break;
else {
int a, b;
re n;
scanf("%d %d", &a, &b);
for (int i = 1; i <= 3100; i++) {
n.num = a;
n.sec = b*i;
s.push(n);
}
}
}
int k;
scanf("%d", &k);
for (int j = 1; j <= k; j++) {
cout << s.top().num << endl;
s.pop();
}
return 0;
}
在网上搜索之后,发现如果使用自定义类型时,需要重载operator<或者重写仿函数。
bool operator<(Node a, Node b){/返回true时,说明a的优先级低于b
/x值较大的Node优先级低(x小的Node排在队前)
/x相等时,y大的优先级低(y小的Node排在队前)
if( a.x== b.x ) return a.y> b.y;
return a.x> b.x;
}
可以写在结构里内部,也可以写在外面。
也可以像结构体排序一样
struct cmp{
bool operator() ( Node a, Node b ){//默认是less函数
//返回true时,a的优先级低于b的优先级(a排在b的后面)
if( a.x== b.x ) return a.y> b.y;
return a.x> b.x; }
};
priority_queue<a, vector<struct a>, cmp> q;
队列的内容大致就到这了,小编还会继续学习和更新。