队列

· · 个人记录

引入

队列(queue)是一种具有先进入队列的元素一定先出队列性质的线性表。由于该性质,队列通常被称为先进先出(first in first out)表,简称 FIFO 表。

实现

数组法

int q[SIZE], l = 1, r;

操作代码:

q[++r] = x;  //加入元素
l++;  //删除元素
q[l];  //访问队首
q[r];  //访问队尾
l = 1, r = 0;  //清空队列

双栈模拟队列(选读)

使用两个栈 q_1, q_2 模拟一个队列,q_2 为队尾栈,q_1 为队首栈。

push : 将数据插入栈 q_1 中。

pop : 如果 q_2 非空,让 q_2 弹栈;否则把 q_1 的元素倒过来压到 q_2 中,然后再让 q_2 弹栈。

复杂度 O(1)

C++ STL

C++ 在 STL 中提供了一个元素叫 queue,使用前需要先引入 <queue> 头文件。 功能中常用的有 :

q.front()  //返回队首元素
q.back()  //返回队尾元素

q.push()  //在队尾插入元素
q.pop()  //弹出队首元素

q.empty()  //队列是否为空
q.size()  //返回队首中元素的数量

q2 = q1    将队列 q1 复制给队列 q2

特殊队列

双端队列

双端队列是指一个可以在队首/队尾插入或删除元素的队列。相当于是栈与队列功能的结合。

数组模拟双端队列的方法限于篇幅不展开,请自行实现。

C++ STL

C++ 在 STL 中也提供了一个容器 deque 使用前需引入头文件 <deque>。

功能中常用的有:

q.front()  <->  返回队首元素
q.back()  <->  返回队尾元素

q.push_back()  <->  在队尾插入元素
q.pop_back()  <->  弹出队尾元素
q.push_front()  <->  在队首插入元素
q.pop_front()  <->  弹出队首元素
q.insert()  <->  在指定位置钱插入元素(传入迭代器和元素)
q.erase()  <->  删除指定位置的元素(传入迭代器)

q.empty()  <->  队列是否为空
q.size()  返回队列中元素的数量

此外,deque 还提供了一些运算符。其中常用的有 :

<queue> 头文件中还提供了优先队列 priority_queue,因其与堆更相似,在此不做介绍。

循环队列

使用数组模拟队列会导致一个问题 : 随着时间的推移,整个队列会向数组的尾部移动,一旦到达数组的最末端,即使数组的前端还有空闲位置,再进行入队操作也会导致溢出(这种数组有空位却上溢的现象被称为 [假溢出] )。

解决假溢出的办法是采用循环的方式来组织存放队列元素的数组,即将数组下标为 0 的位置看做是最后一个位置的后继。(数组下标为 x 的元素,它的后继为 (x + 1) \% n)。这样就形成了循环队列。

习题

洛谷 B3616 【模版】队列

(选做)洛谷 P2827 [NOIP 2016 提高组] 蚯蚓