队列

基本概念

队列与栈相似,采用先进先出的规则,就像排队买票一样
数据结构与算法——队列_指针

相对于栈,队列的结构可能见的更多一些。

STL中的队列

与栈一样,C++的STL库里其实也写好了队列这一结构,可以直接用

#include <iostream>
#include <queue> //STL中的队列头文件
using namespace std;
queue<int> q; //声明一个int型的队列
int main()
{
    int n,t;
    cin>>n;
    for(int i=0;i<n;i++){
        cin>>t;
        q.push(t); //push函数——入队
    }
    while (!q.empty()){
        cout<<q.front()<<" "; //front函数——取队首元素
        q.pop(); //pop函数——出队
    }
    return 0;
}

STL中的队列有如下常用的函数:

  • q.push(n); 元素n入队
  • q.front(); 返回队首元素
  • q.back(); 返回队尾元素
  • q.size(); 返回队列长度
  • q.empty(); 判断q是否为空,空则为1,则为0
  • q.pop(); 队首元素出队

ps. 如果你有一个CLion:
数据结构与算法——队列_算法_02

循环队列

顾名思义,就是把队列的首尾接起来,形成一个循环的队列。队列依旧满足先进先出的规则,只是多了一个首尾相接的功能
数据结构与算法——队列_算法_03

基本结构

队列

#define maxSize 1000
struct Queue{
    int data[maxSize]; //用来存数据
    int front; //队首标记
    int rear; //队尾标记
};

实际上,队列就是换个法子用数组,不采用原来直接调用的方法,而是用两个新的下标

  • 头“指针”front
  • 尾“指针”rear

把这三个东西放到一起,就组成了队列的基本结构。其中数组data用来存储数据,头“指针”front和尾“指针”rear则以下标的形式调用数组data

q.data[q.front]; //队首元素
q.data[q.rear]; //队尾元素

循环

循环主要通过maxSize实现,maxSize是队列的长度。
题解——舞伴问题中的思想一样,采用对maxSize取余的方法,实现循环。在下文“入队”部分中,会进行比较详细的描述。

初始化

void initQueue(Queue &q){
    q.rear=q.front=0;
}

数据结构与算法——队列_队列_04

入队

入队的时候,用到尾指针rear,需要将尾指针后移一位,然后存数据
数据结构与算法——队列_数据结构_05

q.rear++;
q.data[q.rear]=value;

如果队列是循环的,也就是首尾相接,那就会有一个衔接点,一边的下标是0,另一边的下标是maxSize-1

那当q.rear++的时候,如果rear跨过了衔接点,如何表示?

要实现maxSize-1直接跨到0,可以使用取余的方法,当rear=maxSize-1的时候,如果它再+1,我们写:

q.rear=(q.rear+1)%maxSize;

这样的话,+1以后的rear变成了maxSize,取余得0
数据结构与算法——队列_指针_06

void push(Queue &q, int value){
    q.rear=(q.rear+1)%maxSize;
    q.data[q.rear]=value;
}

后续代码中的取余思想与这一环节的基本一致,就不再重复说明。

出队

void pop(Queue &q){
    q.front=(q.front+1)%maxSize;
}

取队首

int top(Queue q){
    return q.data[(q.front+1)%maxSize];
}

判断是否为空

一般情况下,栈和队列中的empty函数,都习惯于让empty=1代表空,让empty=0代表非空

bool empty(Queue q){ 
    return q.rear==q.front; //首尾相等则队列空
}