算法知识-11-队列

队列

在这里插入图片描述

啥是队列(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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值