静态循环队列
食用指南:
对该算法程序编写以及踩坑点很熟悉的同学可以直接跳转到代码模板查看完整代码
只有基础算法的题目会有关于该算法的原理,实现步骤,代码注意点,代码模板,代码误区的讲解
非基础算法的题目侧重题目分析,代码实现,以及必要的代码理解误区
题目描述:
-
实现一个队列,队列初始为空,支持四种操作:
push x – 向队尾插入一个数 x;
pop – 从队头弹出一个数;
empty – 判断队列是否为空;
query – 查询队头元素。
现在要对队列进行 M 个操作,其中的每个操作 3 和操作 4 都要输出相应的结果。输入格式
第一行包含整数 M,表示操作次数。
接下来 M 行,每行包含一个操作命令,操作命令为 push x,pop,empty,query 中的一种。输出格式
对于每个 empty 和 query 操作都要输出一个查询结果,每个结果占一行。
其中,empty 操作的查询结果为 YES 或 NO,query 操作的查询结果为一个整数,表示队头元素的值。数据范围
1≤M≤100000,
1≤x≤109,
所有操作保证合法。输入样例:
10
push 6
empty
query
pop
empty
push 3
push 4
pop
query
push 6
输出样例:
NO
6
YES
4 -
题目来源:https://www.acwing.com/problem/content/831/
题目分析:
- 队列
由于struct占用内存 且 书写和查询速度低下
所以我们采用一个数组 + 双指针 来模拟循环队列
既快速,又省空间
算法原理:
模板算法:
静态循环队列:
- 为什么是循环队列?
普通队列太浪费空间了:尾入头出,头之前有很多废弃空间
1. 存储形式:
- 队列本身:被描述对象有几个属性就开几个数组,本题只有值属性一个
- 队列长:N,int arr[N];
- 队头指针:int head = 0;
- 队尾指针:int tail = 0;
- 为了tail时刻指向空白空间,采用tail++,故初始化tail = 0
- 循环存储:
head++, head %= N;
tail++, tail %= N;
2. 循环队列 的 空/满 判断:
-
队空:
由于初始head == tail == 0
且tail始终指向空白空间
所以当head == tail时表示队头队尾都是空,则队列即空
-
队满:
队列永远空一格,当tail存储完毕后tail++,%N到了这一空格后队满
则tail +1 = head 表示队满
-
可以记为tail == head表示tail没动,是队空
tail +1 = head,则tail动到了head后面,是队满 -
代码实现:
bool empty(){
return tail == head;
}
bool full(){
return tail + 1 == head;
}
3. 尾入元素:
- 插入元素前判断队列是否满了
成功插入则返回索引,失败返回-1
int insert(int x){
if (tail +1 == head)
return -1;
arr[tail] = x;
tail = tail+1%N;
return (tail-1 %N)+N%N;
}
- 不清楚(tail - 1 %N)+N%N是在干什么的同学,看这里:传送门
4. 头出元素:
- 删除元素前判断队列是否空了
成功删除则返回索引,失败返回-1
int remove(){
if(tail == head)
return -1;
head = head+1 % N;
return (head-1%N)+N%N;
}
5. 队头元素:
- head一般指向有元素的空间,而tail一直指向无元素的空间
- 所以直接返回head元素即可,空则返回无穷
int ept = 0x3f3f3f3f3f;
int get_head(){
if (tail == head)
return ept;
return arr[head];
}
代码误区:
1. 循环队列为什么可以循环?
- 一方面是head++ 后马上 head %= N; tail++ 后马上tail %= N;
- 另一方面是队列空一空格子后,队空和队满的判断条件非常清晰
2.head 和 tail 分别指向的是空还是元素?
- tail 永远指向空白空间,所有元素直接放入arr[tail],且一旦放入后++tail %= N;
- head除了队列为空时指向空白空间,之后都指向待出队元素
3. 易错点:先判断空/满 再尾插/头删
4. 静态队列通过增加数组实现结构体字段
- 所有静态队列数组 统一索引于 tail & head
5. 循环队列的生活应用:
- 覆盖记录:
如:一个最近联系人只能记录100条,之后每次新联系一人时,都覆盖了队列中最早联系的那条记录
本篇感想:
- 看完本篇博客,恭喜已登 《练气境-后期》
第35篇左右将进入图论,对dfs bfs不熟悉的小伙伴看这里:【算法设计】用C++类和队列实现图搜索的广度优先遍历算法
距离登仙境不远了,加油