队列
啥是队列(Queue),就是第一个来,第一个走,最后一个来,最后一个走,所谓的先进先出,后进后出。队列是一种特殊的线性表,遵循 “先进先出”(First In First Out,FIFO)的原则
队列-数组操作
入队
//入队函数
void push(int x){
queue[rear] = x;
rear++;
}
出队
//入队函数
void push(int x){
queue[rear] = x;
rear++;
}
获取队首
//获取队首元素
void getFront(){
return queue[front];
}
获取元素个数
//获取队列中元素个数
void size(){
return rear-front;
}
完整函数书写
#include<bits/stdc++.h>
using namespace std;
int queue[10]; //初始化
int front,rear; //front 对首 rear 队尾
//入队函数
void push(int x){
queue[rear] = x;
rear++;
}
//出队函数
void pop(){
front++;
}
//获取队首元素
void getFront(){
return queue[front];
}
//获取队列中元素个数
void size(){
return rear-front;
}
int main(){
return 0;
}
数组操作的队列的题目
4144 队列的操作
描述
输入5个整数,将这5个整数进行入队,接下来做三次出队操作,按照出队顺序输出出队元素,以上操作完成后输出此时的队首元素。
输入描述
输入5个整数,用空格隔开。
输出描述
输出2行,第1行输出出队元素,按照出队顺序输出,用空格隔开。
第2行输出完成出队操作后的队首元素。
样例输入 1
4 9 12 6 7
样例输出 1
4 9 12
6
#include<bits/stdc++.h>
using namespace std;
int q[5];
int front,rear;
void push(int x)
{
if(rear<5)
{
q[rear] = x;
rear++;
}
}
void pop()
{
if(front!=rear)
{
front++;
}
}
int getTop()
{
return q[front];
}
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
int num;
for(int i=1;i<=5;i++)
{
cin>>num;
push(num);
}
for(int i=1;i<=3;i++)
{
cout<<getTop()<<" ";
pop();
}
cout<<"\n"<<getTop();
return 0;
}
6000 破解密码
密码是八位数字,密码由生日作为基数,生成密码的规则如下:
将第1个数字删除,第2个数字放到数字序列末端。
重复执行第一步,直到所有数字删除完毕。
删除的数字将会组成一串新的数字,这就是密码。
输入描述
一行,一组八位数字。
输出描述
一行,八位数字生成的密码。
样例输入 1
20230206
样例输出 1
22000236
解题思路:就是奇数出队,顺便输出出队元素【队首元素】,偶数的时候先出队,再入队
#include<bits/stdc++.h>
using namespace std;
char q[18];
int front,rear,n;
char num[18];
void push(int x)
{
if(rear<200)
{
q[rear] = x;
rear++;
}
}
void pop()
{
if(front!=rear)
{
front++;
}
}
int getTop()
{
return q[front];
}
int size()
{
return rear-front;
}
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
for(int i=1;i<=8;i++)
{
char s;
cin>>s;
push(s);
}
int k=1;
while(size()!=0)
{
if(k%2!=0)
{
cout<<char(getTop());
pop();
}
else
{
push(getTop());
pop();
}
k++;
}
return 0;
}
2927 Blah数集
大数学家高斯小时候偶然间发现一种有趣的自然数集合Blah,对于以a为基的集合Ba定义如下:
(1)a是集合Ba的基,且a是Ba的第一个元素;
(2)如果x在集合Ba中,则2x+1和3x+1也都在集合Ba中;
(3)没有其他元素在集合Ba中了。
现在小高斯想知道如果将集合Ba中元素按照升序排列,第N个元素会是多少?
输入描述
输入包括两个数字,分别是集合的基a(1<=a<=50)以及所求元素序号n(1<=n<=1000000)
输出描述
输出集合Ba的第n个元素值
样例输入 1
1 8
样例输出 1
15
这是一个经典的队列问题
题目说如果集合中有x,则一定有2x+1和3x+1,并且最后要输出从小到大的第n个。
由于x>1,所以一定x<2x+1<3x+1,因此我们可以定义两个队列,分别存放2x+1和3x+1,每一次都取出其中小的那个,执行到第n次时就能得出第n小的数
#include<bits/stdc++.h>
#include<cstdio>
long long a, n;
int q1[100000], front1 = 0, rear1 = 0; // 存放 2x + 1 的数组及队首、队尾指针
int q2[100000], front2 = 0, rear2 = 0; // 存放 3x + 1 的数组及队首、队尾指针
// 出队函数
void pop1() {
front1++;
}
void pop2() {
front2++;
}
// 获取队首元素
int getFront1() {
return q1[front1];
}
int getFront2() {
return q2[front2];
}
// 获取队列中元素个数
int size1() {
return rear1 - front1;
}
int size2() {
return rear2 - front2;
}
int main()
{
scanf("%lld%lld", &a, &n);
n--;
while (n--)
{
q1[rear1++] = 2 * a + 1; // 向数组添加元素
q2[rear2++] = 3 * a + 1; // 向数组添加元素
if (getFront1() < getFront2())
{
a = getFront1();
pop1();
}
else if (getFront1() > getFront2())
{
a = getFront2();
pop2();
}
else
{
a = getFront1();
pop1();
pop2();
}
}
printf("%lld", a);
return 0;
}
2926 密室逃脱
大熊和小鹿周末去密室逃脱,桌面上有n张扑克牌是破解密码的关键。每张扑克牌由(A,2,3,4,5,6,7,8,9,J,Q,K)任意一张组成。生成密码的规则如下:
1 第一张扑克牌拿走,第二张扑克牌挪到剩余扑克牌的最后。
2 将第一步一直执行,直到所有扑克牌拿走。
3 拿走的扑克牌顺序,就是逃脱密码。
同学们帮大熊和小鹿破解密码吧。
输入描述
共2行,第一行,一个整数n,表示有n张扑克牌(1<n<50),第二行,n张扑克牌。
输出描述
一行,表示逃脱密码。
样例输入 1
10
A A J 1 2 K 3 7 Q 6
样例输出 1
A J 2 3 Q A K 6 7 1
#include<bits/stdc++.h>
using namespace std;
char q[100];
int front,rear,n;
char num[100];
void push(int x)
{
if(rear<200)
{
q[rear] = x;
rear++;
}
}
void pop()
{
if(front!=rear)
{
front++;
}
}
int getTop()
{
return q[front];
}
int size()
{
return rear-front;
}
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
cin>>n;
for(int i=1;i<=n;i++)
{
char s;
cin>>s;
push(s);
}
int k=1;
while(size()!=0)
{
if(k%2!=0)
{
cout<<char(getTop())<<" ";
pop();
}
else
{
push(getTop());
pop();
}
k++;
}
return 0;
}
2849 舞会
学校举办了一场舞会,男生和女生在入场时,各自排成一队。伴奏响起时,依次从男队和女队的队首各出一人配成舞伴。规定每个舞曲只有一对跳舞者,若两队初始人数不同,则较长的那一队中未配对者等待下一轮舞曲。请利用程序模拟这个过程。
输入描述
一行,三个数字x,y和n,分别表示男队人数、女队人数和舞曲数目。(1<x,y,n<1000)
输出描述
n行,每行两个数字,表示第i首舞曲的男女配对编号。(男生编号在前,女生编号在后,用一个空格隔开)
样例输入 1
3 5 9
样例输出 1
1 1
2 2
3 3
1 4
2 5
3 1
1 2
2 3
3 4
样例输入 2
3 2 4
样例输出 2
1 1
2 2
3 1
1 2
#include <bits/stdc++.h>
using namespace std;
int x,y,n,j,k;
int main(){
cin>>x>>y>>n;
for(int i=1;i<=n;i++){
j++;
if(j>x) j=1;
cout<<j<<" ";
k++;
if(k>y) k=1;
cout<<k<<'\n';
}
return 0;
}
2848
密码是八位数字,密码由生日作为基数,生成密码的规则如下:
1 将第1个数字删除,第2个数字放到数字末端,再将第3个数字放到数字末端。
2 将第一步一直执行,直到所有数字删除完毕。
3 删除的数字将会组成一串新的数字,这就是密码。
输入描述
一行,一组八位数字。
输出描述
一行,八位数字生成的密码。
样例输入 1
20230206
样例输出 1
23026200
#include<bits/stdc++.h>
using namespace std;
char q[180];
int front,rear,n;
char num[180];
void push(int x)
{
if(rear<200)
{
q[rear] = x;
rear++;
}
}
void pop()
{
if(front!=rear)
{
front++;
}
}
int getTop()
{
return q[front];
}
int size()
{
return rear-front;
}
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
for(int i=1;i<=8;i++)
{
char s;
cin>>s;
push(s);
}
int k=1;
while(size()!=0)
{
if(k%3==1)
{
cout<<char(getTop());
pop();
}
else
{
push(getTop());
pop();
}
k++;
}
return 0;
}
1628 排队问题
有 n 个人排队,每个人有一个编号 i( 1 ≤ i ≤ n ),从左往右“ 1,2,1,2,…”报数,报到“ 1 ”的人出列,数到“ 2 ”的人立即占到队伍的最右端。报数过程反复进行,直到 n 个人都出列为止。已知 n个人原来的顺序,请写出他们的出列顺序。
输入描述
第一行为 n( n≤100 ),第二行为 n 个编号 i( 1≤i≤n),且 i 不会重复。
输出描述
一行,为他们的出列编号。
样例输入 1
8
1 2 3 4 5 6 7 8
样例输出 1
1 3 5 7 2 6 4 8
样例输入 2
4
2 5 1 3
样例输出 2
2 1 5 3
#include<bits/stdc++.h>
using namespace std;
int q[205],front,rear,n,num;
void push(int x)
{
if(rear<200)
{
q[rear] = x;
rear++;
}
}
void pop()
{
if(front!=rear)
{
front++;
}
}
int getTop()
{
return q[front];
}
int size()
{
return rear-front;
}
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>num;
push(num);
}
int k=1;
while(size()!=0)
{
if(k%2!=0)
{
cout<<getTop()<<" ";
pop();
}
else
{
push(getTop());
pop();
}
k++;
}
return 0;
}
1393 选标兵
童童所在的学校开始军训了,在军训的时候会选出一些标兵,作为队列的标尺,穿着军装拿着枪,很帅,童童也想当标兵,候选人很多,老师想到一个办法,假如有 M 个人选,每人一个编号分别为 1 ~ M。这 M 个人按顺序排成一个圈。现在给定一个数 N,从第一个人开始依次报数,数到 N 的人出列,然后又从下一个人开始又从 1 开始依次报数,数到 N 的人又出列...如此循环,直到最后一个人出列为止。按照出列顺序然后选拔标兵,够了为止,童童想提前算出这个出列顺序,那么他好看看站在什么位置合适,现在我们大家一起来帮忙帮他计算出出列顺序吧。
输入描述
输入只有一行,包括 2 个整数 M (8≤M≤15),N(5≤N≤32767)。之间用一个空格分开。
输出描述
输出 M 行,每行一个整数(出列顺序)。
样例输入 1
9 6
样例输出 1
6
3
1
9
2
5
4
8
7
#include<bits/stdc++.h>
using namespace std;
char q[1500000];
int front,rear,n,m;
char num[1500000];
void push(int x)
{
q[rear] = x;
rear++;
}
void pop()
{
if(front!=rear)
{
front++;
}
}
int getTop()
{
return q[front];
}
int size()
{
return rear-front;
}
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
cin>>n>>m;
for(int i=1;i<=n;i++)
{
push(i);
}
int k=0;
while(size()!=0)
{
k++;
if(k%m==0)
{
k = 0;
cout<<getTop()<<'\n';
pop();
}
else
{
push(getTop());
pop();
}
}
return 0;
}
1391 纸牌问题
桌面有一叠牌,从第一张(即位于顶面的牌)开始从上往下依次编号为 1∼n。当至少还剩两张牌时进行以下操作:把第一张牌扔掉,然后把新的第一张放到整叠牌的最后。输入 n,输出每次扔掉的牌,以及最后剩下的牌 (3≤n≤100)。
输入描述
一个整数 n,牌的数量。
输出描述
输出每次扔掉的牌以及最后剩下的牌
样例输入 1
7
样例输出 1
1 3 5 7 4 2 6
#include<bits/stdc++.h>
using namespace std;
char q[200];
int front,rear,n;
char num[200];
void push(int x)
{
if(rear<200)
{
q[rear] = x;
rear++;
}
}
void pop()
{
if(front!=rear)
{
front++;
}
}
int getTop()
{
return q[front];
}
int size()
{
return rear-front;
}
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
cin>>n;
for(int i=1;i<=n;i++)
{
push(i);
}
int k=1;
while(size()!=0)
{
if(k%2!=0)
{
cout<<getTop()<<" ";
pop();
}
else
{
push(getTop());
pop();
}
k++;
}
return 0;
}