【数据结构】队列的应用:循环队列

考点频率 :★★★★★(数据结构必考,选择题每年至少1题,尤其爱考判空/判满条件)

难度 :⭐⭐⭐

建议:重点理解循环队列解决"假溢出"的原理,掌握判空、判满、元素个数三个公式

1️⃣ 为什么需要循环队列?

上一篇文章我们讲了顺序队列(数组实现)。它有一个严重的问题:假溢出(False Overflow)

假溢出的产生过程

  1. 初始状态:front = rear = 0,队列为空
  2. 入队 A、B、C、D:rear 移动到 4
  3. 出队 A、B:front 移动到 2
  4. 此时数组前两个位置(0和1)已经空闲,但 rear 已经在 4,无法再入队新元素

明明数组前面还有空闲空间,却无法使用------这就是"假溢出"。

解决方案 :把数组的首尾逻辑上连接起来 ,形成一个环形。当 rear 到达数组末尾时,下一步就绕回到数组开头------这就是循环队列(Circular Queue)

2️⃣ 循环队列的核心约定

循环队列使用两个指针:

  • front:指向队头元素的位置
  • rear:指向队尾元素的下一个位置(即下一个入队的位置)

三个核心公式(必背)

操作 公式
判空 front == rear
判满 (rear + 1) % MAXSIZE == front
元素个数 (rear - front + MAXSIZE) % MAXSIZE

⚠️ 注意 :循环队列中,为了区分"空"和"满",我们牺牲一个存储单元 ------当 (rear+1) % MAXSIZE == front 时判满,此时实际上还有一个空位没有放数据(即该位置不存储元素,仅作为"满"的判定标记,保证 front == rear 只代表空)。这是最常见的实现方式,考试也默认采用这种约定。

3️⃣ 为什么牺牲一个空间?

如果不牺牲空间,front == rear 可能代表"空"也可能代表"满":

情况 front rear 含义
空队列 0 0 front == rear
满队列 0 0 front == rear(绕了一圈回到原点)

同一个条件无法区分两种情况。所以牺牲一个空间 ,让"满"的条件变成 (rear+1) % MAXSIZE == front,这样就和"空"的条件区分开了。

4️⃣ 循环队列的基本操作

4.1 入队(Enqueue)

c 复制代码
int Enqueue(SeqQueue* q, int x) {
    if ((q->rear + 1) % MAXSIZE == q->front) {
        return -1;   // 队列已满
    }
    q->data[q->rear] = x;
    q->rear = (q->rear + 1) % MAXSIZE;
    return 0;
}

4.2 出队(Dequeue)

c 复制代码
int Dequeue(SeqQueue* q, int* x) {
    if (q->front == q->rear) {
        return -1;   // 队列为空
    }
    *x = q->data[q->front];
    q->front = (q->front + 1) % MAXSIZE;
    return 0;
}

4.3 元素个数计算

c 复制代码
int GetLength(SeqQueue* q) {
    return (q->rear - q->front + MAXSIZE) % MAXSIZE;
}

5️⃣ 例题详解

例题1 :某循环队列的数组大小为 6,front = 2rear = 5,则队列中的元素个数为( )。

A. 2

B. 3

C. 4

D. 5

解析

  • 元素个数 = (rear - front + MAXSIZE) % MAXSIZE
  • = (5 - 2 + 6) % 6 = 9 % 6 = 3
  • B

例题2 :某循环队列的数组大小为 8,若 front = 3,则 rear 为多少时表示队列已满?

A. 2

B. 3

C. 4

D. 6

解析

  • 判满条件:(rear + 1) % 8 == front
  • 代入 front = 3(rear + 1) % 8 == 3
  • 满足条件的 rear = 2(因为 (2+1)%8=3
  • A

例题3 (变式):某循环队列的数组大小为 5,当前 front = 3rear = 2,再入队一个元素后,frontrear 的值分别是多少?

解析

  • 当前元素个数 = (2 - 3 + 5) % 5 = 4 % 5 = 4
  • 数组大小为5,牺牲1个空间,最多存4个元素
  • 当前已经存了4个,队列已满,无法入队
  • 入队失败,frontrear 不变:front=3rear=2

答案 :无法入队,front=3rear=2

6️⃣ 三种处理"满/空"的方式

除了"牺牲一个空间"外,还有其他方式可以区分满和空。考试偶尔会涉及:

方案 判空 判满 说明
牺牲一个空间 front == rear (rear+1)%MAXSIZE == front 最常见,考试默认方案
增加 size 变量 size == 0 size == MAXSIZE 多一个变量记录元素个数,无需牺牲空间
增加 flag 变量 flag == 0 && front==rear flag == 1 && front==rear 用 flag 标记最后一次操作是入队还是出队

考试提示 :如果题目没有特别说明,默认采用牺牲一个空间 的方案。如果题目说"队列中有一个size变量记录元素个数",则判空判满条件要用 size

7️⃣ 记忆口诀

循环队列首尾连,假溢出问题不再现。

front == rear 为空,(rear+1)%max == front 为满。

元素个数公式记:(rear - front + max) % max

8️⃣ 小测验(评论区对答案)

某循环队列的数组大小为 10,当前 front = 6rear = 4,队列中元素个数为( )。再入队两个元素后,frontrear 的值分别是多少?

A. 8;front=6rear=6

B. 8;front=6rear=8

C. 6;front=6rear=8

D. 6;front=6rear=6

🔔 本专栏日更,点击头像 → 专栏《软考中级高频考点》订阅,第一时间接收新内容

#软考中级 #软件设计师 #循环队列 #队列 #数据结构 #软考备考

相关推荐
荆棘鸟智能23 分钟前
城市感知设备怎么统一接入?从多协议网关到设备模型的中间件架构设计
人工智能·算法·边缘计算
淡海水1 小时前
13-04-面试-源码级深度追问链
数据结构·unity·面试·c#·游戏引擎·源码·il2cpp
Logic1011 小时前
C语言/数据结构位运算题解:异或XOR找出时尚聚会中的“独特颜色“——只出现一次的数字
c语言·数据结构·数组·位运算·时间复杂度·算法题·异或性质
INGNIGHT4 小时前
270 · 电话号码的字母组合II(Trie)
linux·算法
马可家的菠萝5 小时前
你收藏的资料,有多少真的被你第二次打开过?
笔记·知识管理·效率提升·个人知识库
2401_839080545 小时前
C++常见八股
数据结构·c++·算法
青山是哪个青山5 小时前
LeetCode 188:买卖股票的最佳时机 IV
算法
暮雨封夕5 小时前
跳表(Skip List)详解:原理、实现、使用场景与实际应用
数据结构
mikuyyds5 小时前
geo-toolbox 插件算法解析:RUSLE 与 MUSLE 的工程化落地
算法·rust·gis
a187927218315 小时前
【算法】树(二):队列与祖先——BFS 骨架三配件、短路透传与合流
算法·leetcode·二叉树··bfs·算法讲解·树遍历