队列

定义:

1. 队列(queue)是一种特殊的线性数据结构,队列中的元素也是按照入队顺
序线性的排列。
2.队列的结构如下图所示,队列只允许在队列的前端(队头)进行删除操作,
后端(队尾)进行插入操作。
3.队列的特点是先进先出(FIFO,First In First Out),即最先入队列的元素
最先出队列,就和我们平时排队一样。

 

队列的实现:

1.队列的基本操作包括入队、出队、判断队列是否为空、求队列中元素的个数(队列长度)等。
我们可以用一个数组简单的实现队列的所有操作。

数组模拟(手工队列):

 STL队列:

队列的应用:

1.队列在计算机科学中应用也十分广泛。
2.队列的主要应用是在BFS(广度优先搜索)中。
3.此外,我们要讲的「单调队列」也是队列的重要用途之一。

初识队列:

队列例题:

http://ybt.ssoier.cn:8088/problem_show.php?pid=1332

1332:【例2-1】周末舞会

时间限制: 1000 ms         内存限制: 65536 KB

【题目描述】

  假设在周末舞会上,男士们和女士们进入舞厅时,各自排成一队。跳舞开始时,依次从男队和女队的队头上各出一人配成舞伴。规定每个舞曲能有一对跳舞者。若两队初始人数不相同,则较长的那一队中未配对者等待下一轮舞曲。现要求写一个程序,模拟上述舞伴配对问题。

【输入】

第一行两队的人数;

第二行舞曲的数目。

【输出】

  配对情况。

【输入样例】

4 6
7

【输出样例】

1 1
2 2
3 3
4 4
1 5
2 6
3 1
STL队列:
#include<bits/stdc++.h>//#include<queue>
using namespace std;
int main(){
    int n,m;//男生人数. 女生人数. 
    cin>>n>>m;
    int x;//歌曲数. 
    cin>>x;
    queue<int> q;//男队列. 
    queue<int> p;//女队列. 
    for(int i=1;i<=n;i++) q.push(i);//将男队列依次进行编号. 
    for(int i=1;i<=m;i++) p.push(i);//将女队列依次进行编号. 
    for(int i=0;i<x;i++){//循环x次. 
        cout<<q.front()<<' '<<p.front()<<endl;//输出男女编号. 
        q.push(q.front());//放入刚刚出队的男生. 
        p.push(p.front());//放入刚刚出队的女生. 
        q.pop();//now头男生出队. 
        p.pop();//now头女生出队. 
    }
    return 0;
}
手工队列:
#include<bits/stdc++.h>
using namespace std;
int main(){
    int n1,n2;
    cin>>n1>>n2;
    int m;
    cin>>m;
    int q1[100],q2[100];
    for(int i=1;i<=n1;i++) q1[i]=i;
    for(int i=1;i<=n2;i++) q2[i]=i;
    int f1=1,r1=n1,f2=1,r2=n2;
    for(int i=0;i<m;i++){
        cout<<q1[f1]<<" "<<q2[f2]<<endl;
        q1[++r1]=q1[f1++];
        q2[++r2]=q2[f2++];
    }
    return 0;
}               

http://ybt.ssoier.cn:8088/problem_show.php?pid=1334

1334:【例2-3】围圈报数


时间限制: 1000 ms         内存限制: 65536 KB

【题目描述】

  有n个人依次围成一圈,从第1个人开始报数,数到第m个人出列,然后从出列的下一个人开始报数,数到第m个人又出列,…,如此反复到所有的人全部出列为止。设n个人的编号分别为12n1,2,…,n,打印出列的顺序。

【输入】

nn和mm。

【输出】

出列的顺序。

【输入样例】

4 17

【输出样例】

1 3 4 2

【提示】

n100n≤100。

STL队列:

#include<bits/stdc++.h>//#include<queue>
using namespace std;
int main(){
    queue<int> q;
    int n,m;
    int now=1;
    cin>>n>>m;
    for(int i=1;i<=n;i++) q.push(i);
    while(!q.empty( )){
        if(now==m){
            cout<<q.front( )<<" ";
            q.pop( );
            now=1;
        }else{
            q.push(q.front( ));
            q.pop( );
            now++;
        }
    }
    return 0;
}

手工队列:

#include<bits/stdc++.h>
using namespace std;
int main(){    
    int q[100];
    int f=0,r=0;
    int n,m,now=1;
    cin>>n>>m;
    for(int i=1;i<=n;i++) q[r++]=i;
    while(f<r){
        if(now==m){
           cout<<q[f]<<' ';
           f++;
           now=1;
        }else{
           q[r++]=q[f++];
           now++;
        }  
    }
    return 0;
}

http://ybt.ssoier.cn:8088/problem_show.php?pid=1333

1333:【例2-2】Blah数集

时间限制: 1000 ms         内存限制: 65536 KB

【题目描述】

大数学家高斯小时候偶然间发现一种有趣的自然数集合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 100
28 5437

【输出样例】

418
900585
算法分析:
 维护三个数组q1,q2,q3;取q2、q3队头元素的较小者k出队,并加入q1,2*k+1、3*k+1分别加入q2、q3;
直到q1中的元素个数达到n个。实际上,q2、q3中的元素都来自于q1,实际上,q2、q3中的元素都来自于q1,
只要维护head2、head3两个位置,表示q2中的下一个数由q1[head2] *2+1得到,q3中的下一个数由
q1[head3]*3+1得到,这样就不需要q2、q3这两个数组了。特殊情况的处理:q2、q3的队头元素相同。
#include<bits/stdc++.h>
using namespace std;
const int M=1000009;
typedef long long ll;
ll q[M];
void work(int a,int n){
    q[1]=a;//初始元素入队
    int head2=1,head3=1,tail=1;//初始队列指针,tail是队尾元素下标
    while(tail<=n){    
    ll t1=2*q[head2]+1,t2=3*q[head3]+1;
        ll t=min(t1,t2);
        if(t1<t2) head2++;//出队
        else head3++;
        if(t!=q[tail]) q[++tail]=t;//入队,且重复元素不入队
    }
    cout<<q[n]<<endl;
}
int main(){
    int a,n;
    while(cin>>a>>n) work(a,n);
    return 0;
}

虽然AC了,但是while停不下来.本人蒟蒻一个,请大佬评论提建议.

作者洛古

https://www.luogu.com.cn/user/685031

队列队列队列队列队列队列队列队列队列队列队列队列队列队列队列队列队列队列队列队列队列队列队列队列队列队列队列队列队列队列