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

考点频率 :★★★★★(数据结构必考,选择题每年至少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 = 2,rear = 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 = 3,rear = 2,再入队一个元素后,front 和 rear 的值分别是多少?

解析:

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

答案 :无法入队,front=3,rear=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 = 6,rear = 4,队列中元素个数为( )。再入队两个元素后,front 和 rear 的值分别是多少?

A. 8;front=6,rear=6

B. 8;front=6,rear=8

C. 6;front=6,rear=8

D. 6;front=6,rear=6

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

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

相关推荐
Zachery Pole2 小时前
具身智能强化学习(1)引言
算法·机器学习
All for pursuit.2 小时前
【动态规划-11】279.完全平方数
数据结构·c++·算法·leetcode·动态规划
淡海水2 小时前
02-06-原理篇-增量式GC与并发GC
算法·unity·c#·并发·gc·增量
对空六课2 小时前
无头浏览器访问对跳出率的过滤规则
服务器·前端·算法·数据分析
有同事要进步2 小时前
leecode第一题-两数字之和(打卡)
算法
程序员清风2 小时前
二叉搜索树:查找、插入与删除
算法
HRTOS2 小时前
HRTOS 内核 BUG 修复:任务等待对象未初始化导致的异常唤醒问题
单片机·嵌入式硬件·算法·51单片机
XMAIPC_Robot3 小时前
国产FPGA替代Xilinx在储能电力采集场景可行性评估与移植经验
人工智能·算法·机器学习·fpga开发·rk3588+fpga
开开心心就好3 小时前
一元二次方程求解工具,答案带详细步骤
java·服务器·开发语言·算法·pdf·ocr·perl
Logic1013 小时前
C语言/数据结构位运算题解:异或XOR找出套碗游戏中的“幸运碗“——只出现一次的数字
c语言·数据结构·算法·数组·位运算·时间复杂度·空间复杂度