【408数据结构 08】队列:循环队列判空判满,408年年考,一次讲清

【408数据结构 08】队列:循环队列判空判满,408年年考,一次讲清

专栏导航 :本篇是《408数据结构:C++手写实现 + 图解 + 真题》第 08 篇。

上一篇 :【408数据结构 07】栈:408每年必考,这3个坑90%的人会踩

下一篇:【408数据结构 09】栈和队列应用:括号匹配、表达式求值、递归

### 文章目录

  • [【408数据结构 08】队列:循环队列判空判满,408年年考,一次讲清](#文章目录 【408数据结构 08】队列:循环队列判空判满,408年年考,一次讲清 @[toc] 先做个自测 一、队列到底是什么?一句话:先进先出 二、408 怎么考队列?先看真题分布 三、顺序队列:为什么需要循环? 3.1 普通顺序队列的“假溢出” 3.2 循环队列图解 四、循环队列的三种判空判满方法(408 核心) 4.1 方法一:牺牲一个存储单元(最常考) 4.2 方法二:设置 size 变量 4.3 方法三:设置 tag 标志 五、链队列:用链表实现队列 六、双端队列:408 新宠 6.1 三种双端队列 6.2 408 常考问法 6.3 双端队列的快速判断 七、真题演练 7.1 循环队列判满 7.2 循环队列元素个数 7.3 链队列出队 7.4 双端队列 八、一句话记住队列 九、总结与下一篇预告)
  • [@toc](#文章目录 【408数据结构 08】队列:循环队列判空判满,408年年考,一次讲清 @[toc] 先做个自测 一、队列到底是什么?一句话:先进先出 二、408 怎么考队列?先看真题分布 三、顺序队列:为什么需要循环? 3.1 普通顺序队列的“假溢出” 3.2 循环队列图解 四、循环队列的三种判空判满方法(408 核心) 4.1 方法一:牺牲一个存储单元(最常考) 4.2 方法二:设置 size 变量 4.3 方法三:设置 tag 标志 五、链队列:用链表实现队列 六、双端队列:408 新宠 6.1 三种双端队列 6.2 408 常考问法 6.3 双端队列的快速判断 七、真题演练 7.1 循环队列判满 7.2 循环队列元素个数 7.3 链队列出队 7.4 双端队列 八、一句话记住队列 九、总结与下一篇预告)
  • [先做个自测](#文章目录 【408数据结构 08】队列:循环队列判空判满,408年年考,一次讲清 @[toc] 先做个自测 一、队列到底是什么?一句话:先进先出 二、408 怎么考队列?先看真题分布 三、顺序队列:为什么需要循环? 3.1 普通顺序队列的“假溢出” 3.2 循环队列图解 四、循环队列的三种判空判满方法(408 核心) 4.1 方法一:牺牲一个存储单元(最常考) 4.2 方法二:设置 size 变量 4.3 方法三:设置 tag 标志 五、链队列:用链表实现队列 六、双端队列:408 新宠 6.1 三种双端队列 6.2 408 常考问法 6.3 双端队列的快速判断 七、真题演练 7.1 循环队列判满 7.2 循环队列元素个数 7.3 链队列出队 7.4 双端队列 八、一句话记住队列 九、总结与下一篇预告)
  • [一、队列到底是什么?一句话:先进先出](#文章目录 【408数据结构 08】队列:循环队列判空判满,408年年考,一次讲清 @[toc] 先做个自测 一、队列到底是什么?一句话:先进先出 二、408 怎么考队列?先看真题分布 三、顺序队列:为什么需要循环? 3.1 普通顺序队列的“假溢出” 3.2 循环队列图解 四、循环队列的三种判空判满方法(408 核心) 4.1 方法一:牺牲一个存储单元(最常考) 4.2 方法二:设置 size 变量 4.3 方法三:设置 tag 标志 五、链队列:用链表实现队列 六、双端队列:408 新宠 6.1 三种双端队列 6.2 408 常考问法 6.3 双端队列的快速判断 七、真题演练 7.1 循环队列判满 7.2 循环队列元素个数 7.3 链队列出队 7.4 双端队列 八、一句话记住队列 九、总结与下一篇预告)
  • [二、408 怎么考队列?先看真题分布](#文章目录 【408数据结构 08】队列:循环队列判空判满,408年年考,一次讲清 @[toc] 先做个自测 一、队列到底是什么?一句话:先进先出 二、408 怎么考队列?先看真题分布 三、顺序队列:为什么需要循环? 3.1 普通顺序队列的“假溢出” 3.2 循环队列图解 四、循环队列的三种判空判满方法(408 核心) 4.1 方法一:牺牲一个存储单元(最常考) 4.2 方法二:设置 size 变量 4.3 方法三:设置 tag 标志 五、链队列:用链表实现队列 六、双端队列:408 新宠 6.1 三种双端队列 6.2 408 常考问法 6.3 双端队列的快速判断 七、真题演练 7.1 循环队列判满 7.2 循环队列元素个数 7.3 链队列出队 7.4 双端队列 八、一句话记住队列 九、总结与下一篇预告)
  • [三、顺序队列:为什么需要循环?](#文章目录 【408数据结构 08】队列:循环队列判空判满,408年年考,一次讲清 @[toc] 先做个自测 一、队列到底是什么?一句话:先进先出 二、408 怎么考队列?先看真题分布 三、顺序队列:为什么需要循环? 3.1 普通顺序队列的“假溢出” 3.2 循环队列图解 四、循环队列的三种判空判满方法(408 核心) 4.1 方法一:牺牲一个存储单元(最常考) 4.2 方法二:设置 size 变量 4.3 方法三:设置 tag 标志 五、链队列:用链表实现队列 六、双端队列:408 新宠 6.1 三种双端队列 6.2 408 常考问法 6.3 双端队列的快速判断 七、真题演练 7.1 循环队列判满 7.2 循环队列元素个数 7.3 链队列出队 7.4 双端队列 八、一句话记住队列 九、总结与下一篇预告)
  • [3.1 普通顺序队列的"假溢出"](#文章目录 【408数据结构 08】队列:循环队列判空判满,408年年考,一次讲清 @[toc] 先做个自测 一、队列到底是什么?一句话:先进先出 二、408 怎么考队列?先看真题分布 三、顺序队列:为什么需要循环? 3.1 普通顺序队列的“假溢出” 3.2 循环队列图解 四、循环队列的三种判空判满方法(408 核心) 4.1 方法一:牺牲一个存储单元(最常考) 4.2 方法二:设置 size 变量 4.3 方法三:设置 tag 标志 五、链队列:用链表实现队列 六、双端队列:408 新宠 6.1 三种双端队列 6.2 408 常考问法 6.3 双端队列的快速判断 七、真题演练 7.1 循环队列判满 7.2 循环队列元素个数 7.3 链队列出队 7.4 双端队列 八、一句话记住队列 九、总结与下一篇预告)
  • [3.2 循环队列图解](#文章目录 【408数据结构 08】队列:循环队列判空判满,408年年考,一次讲清 @[toc] 先做个自测 一、队列到底是什么?一句话:先进先出 二、408 怎么考队列?先看真题分布 三、顺序队列:为什么需要循环? 3.1 普通顺序队列的“假溢出” 3.2 循环队列图解 四、循环队列的三种判空判满方法(408 核心) 4.1 方法一:牺牲一个存储单元(最常考) 4.2 方法二:设置 size 变量 4.3 方法三:设置 tag 标志 五、链队列:用链表实现队列 六、双端队列:408 新宠 6.1 三种双端队列 6.2 408 常考问法 6.3 双端队列的快速判断 七、真题演练 7.1 循环队列判满 7.2 循环队列元素个数 7.3 链队列出队 7.4 双端队列 八、一句话记住队列 九、总结与下一篇预告)
  • [四、循环队列的三种判空判满方法(408 核心)](#文章目录 【408数据结构 08】队列:循环队列判空判满,408年年考,一次讲清 @[toc] 先做个自测 一、队列到底是什么?一句话:先进先出 二、408 怎么考队列?先看真题分布 三、顺序队列:为什么需要循环? 3.1 普通顺序队列的“假溢出” 3.2 循环队列图解 四、循环队列的三种判空判满方法(408 核心) 4.1 方法一:牺牲一个存储单元(最常考) 4.2 方法二:设置 size 变量 4.3 方法三:设置 tag 标志 五、链队列:用链表实现队列 六、双端队列:408 新宠 6.1 三种双端队列 6.2 408 常考问法 6.3 双端队列的快速判断 七、真题演练 7.1 循环队列判满 7.2 循环队列元素个数 7.3 链队列出队 7.4 双端队列 八、一句话记住队列 九、总结与下一篇预告)
  • [4.1 方法一:牺牲一个存储单元(最常考)](#文章目录 【408数据结构 08】队列:循环队列判空判满,408年年考,一次讲清 @[toc] 先做个自测 一、队列到底是什么?一句话:先进先出 二、408 怎么考队列?先看真题分布 三、顺序队列:为什么需要循环? 3.1 普通顺序队列的“假溢出” 3.2 循环队列图解 四、循环队列的三种判空判满方法(408 核心) 4.1 方法一:牺牲一个存储单元(最常考) 4.2 方法二:设置 size 变量 4.3 方法三:设置 tag 标志 五、链队列:用链表实现队列 六、双端队列:408 新宠 6.1 三种双端队列 6.2 408 常考问法 6.3 双端队列的快速判断 七、真题演练 7.1 循环队列判满 7.2 循环队列元素个数 7.3 链队列出队 7.4 双端队列 八、一句话记住队列 九、总结与下一篇预告)
  • [4.2 方法二:设置 size 变量](#文章目录 【408数据结构 08】队列:循环队列判空判满,408年年考,一次讲清 @[toc] 先做个自测 一、队列到底是什么?一句话:先进先出 二、408 怎么考队列?先看真题分布 三、顺序队列:为什么需要循环? 3.1 普通顺序队列的“假溢出” 3.2 循环队列图解 四、循环队列的三种判空判满方法(408 核心) 4.1 方法一:牺牲一个存储单元(最常考) 4.2 方法二:设置 size 变量 4.3 方法三:设置 tag 标志 五、链队列:用链表实现队列 六、双端队列:408 新宠 6.1 三种双端队列 6.2 408 常考问法 6.3 双端队列的快速判断 七、真题演练 7.1 循环队列判满 7.2 循环队列元素个数 7.3 链队列出队 7.4 双端队列 八、一句话记住队列 九、总结与下一篇预告)
  • [4.3 方法三:设置 tag 标志](#文章目录 【408数据结构 08】队列:循环队列判空判满,408年年考,一次讲清 @[toc] 先做个自测 一、队列到底是什么?一句话:先进先出 二、408 怎么考队列?先看真题分布 三、顺序队列:为什么需要循环? 3.1 普通顺序队列的“假溢出” 3.2 循环队列图解 四、循环队列的三种判空判满方法(408 核心) 4.1 方法一:牺牲一个存储单元(最常考) 4.2 方法二:设置 size 变量 4.3 方法三:设置 tag 标志 五、链队列:用链表实现队列 六、双端队列:408 新宠 6.1 三种双端队列 6.2 408 常考问法 6.3 双端队列的快速判断 七、真题演练 7.1 循环队列判满 7.2 循环队列元素个数 7.3 链队列出队 7.4 双端队列 八、一句话记住队列 九、总结与下一篇预告)
  • [五、链队列:用链表实现队列](#文章目录 【408数据结构 08】队列:循环队列判空判满,408年年考,一次讲清 @[toc] 先做个自测 一、队列到底是什么?一句话:先进先出 二、408 怎么考队列?先看真题分布 三、顺序队列:为什么需要循环? 3.1 普通顺序队列的“假溢出” 3.2 循环队列图解 四、循环队列的三种判空判满方法(408 核心) 4.1 方法一:牺牲一个存储单元(最常考) 4.2 方法二:设置 size 变量 4.3 方法三:设置 tag 标志 五、链队列:用链表实现队列 六、双端队列:408 新宠 6.1 三种双端队列 6.2 408 常考问法 6.3 双端队列的快速判断 七、真题演练 7.1 循环队列判满 7.2 循环队列元素个数 7.3 链队列出队 7.4 双端队列 八、一句话记住队列 九、总结与下一篇预告)
  • [六、双端队列:408 新宠](#文章目录 【408数据结构 08】队列:循环队列判空判满,408年年考,一次讲清 @[toc] 先做个自测 一、队列到底是什么?一句话:先进先出 二、408 怎么考队列?先看真题分布 三、顺序队列:为什么需要循环? 3.1 普通顺序队列的“假溢出” 3.2 循环队列图解 四、循环队列的三种判空判满方法(408 核心) 4.1 方法一:牺牲一个存储单元(最常考) 4.2 方法二:设置 size 变量 4.3 方法三:设置 tag 标志 五、链队列:用链表实现队列 六、双端队列:408 新宠 6.1 三种双端队列 6.2 408 常考问法 6.3 双端队列的快速判断 七、真题演练 7.1 循环队列判满 7.2 循环队列元素个数 7.3 链队列出队 7.4 双端队列 八、一句话记住队列 九、总结与下一篇预告)
  • [6.1 三种双端队列](#文章目录 【408数据结构 08】队列:循环队列判空判满,408年年考,一次讲清 @[toc] 先做个自测 一、队列到底是什么?一句话:先进先出 二、408 怎么考队列?先看真题分布 三、顺序队列:为什么需要循环? 3.1 普通顺序队列的“假溢出” 3.2 循环队列图解 四、循环队列的三种判空判满方法(408 核心) 4.1 方法一:牺牲一个存储单元(最常考) 4.2 方法二:设置 size 变量 4.3 方法三:设置 tag 标志 五、链队列:用链表实现队列 六、双端队列:408 新宠 6.1 三种双端队列 6.2 408 常考问法 6.3 双端队列的快速判断 七、真题演练 7.1 循环队列判满 7.2 循环队列元素个数 7.3 链队列出队 7.4 双端队列 八、一句话记住队列 九、总结与下一篇预告)
  • [6.2 408 常考问法](#文章目录 【408数据结构 08】队列:循环队列判空判满,408年年考,一次讲清 @[toc] 先做个自测 一、队列到底是什么?一句话:先进先出 二、408 怎么考队列?先看真题分布 三、顺序队列:为什么需要循环? 3.1 普通顺序队列的“假溢出” 3.2 循环队列图解 四、循环队列的三种判空判满方法(408 核心) 4.1 方法一:牺牲一个存储单元(最常考) 4.2 方法二:设置 size 变量 4.3 方法三:设置 tag 标志 五、链队列:用链表实现队列 六、双端队列:408 新宠 6.1 三种双端队列 6.2 408 常考问法 6.3 双端队列的快速判断 七、真题演练 7.1 循环队列判满 7.2 循环队列元素个数 7.3 链队列出队 7.4 双端队列 八、一句话记住队列 九、总结与下一篇预告)
  • [6.3 双端队列的快速判断](#文章目录 【408数据结构 08】队列:循环队列判空判满,408年年考,一次讲清 @[toc] 先做个自测 一、队列到底是什么?一句话:先进先出 二、408 怎么考队列?先看真题分布 三、顺序队列:为什么需要循环? 3.1 普通顺序队列的“假溢出” 3.2 循环队列图解 四、循环队列的三种判空判满方法(408 核心) 4.1 方法一:牺牲一个存储单元(最常考) 4.2 方法二:设置 size 变量 4.3 方法三:设置 tag 标志 五、链队列:用链表实现队列 六、双端队列:408 新宠 6.1 三种双端队列 6.2 408 常考问法 6.3 双端队列的快速判断 七、真题演练 7.1 循环队列判满 7.2 循环队列元素个数 7.3 链队列出队 7.4 双端队列 八、一句话记住队列 九、总结与下一篇预告)
  • [七、真题演练](#文章目录 【408数据结构 08】队列:循环队列判空判满,408年年考,一次讲清 @[toc] 先做个自测 一、队列到底是什么?一句话:先进先出 二、408 怎么考队列?先看真题分布 三、顺序队列:为什么需要循环? 3.1 普通顺序队列的“假溢出” 3.2 循环队列图解 四、循环队列的三种判空判满方法(408 核心) 4.1 方法一:牺牲一个存储单元(最常考) 4.2 方法二:设置 size 变量 4.3 方法三:设置 tag 标志 五、链队列:用链表实现队列 六、双端队列:408 新宠 6.1 三种双端队列 6.2 408 常考问法 6.3 双端队列的快速判断 七、真题演练 7.1 循环队列判满 7.2 循环队列元素个数 7.3 链队列出队 7.4 双端队列 八、一句话记住队列 九、总结与下一篇预告)
  • [7.1 循环队列判满](#文章目录 【408数据结构 08】队列:循环队列判空判满,408年年考,一次讲清 @[toc] 先做个自测 一、队列到底是什么?一句话:先进先出 二、408 怎么考队列?先看真题分布 三、顺序队列:为什么需要循环? 3.1 普通顺序队列的“假溢出” 3.2 循环队列图解 四、循环队列的三种判空判满方法(408 核心) 4.1 方法一:牺牲一个存储单元(最常考) 4.2 方法二:设置 size 变量 4.3 方法三:设置 tag 标志 五、链队列:用链表实现队列 六、双端队列:408 新宠 6.1 三种双端队列 6.2 408 常考问法 6.3 双端队列的快速判断 七、真题演练 7.1 循环队列判满 7.2 循环队列元素个数 7.3 链队列出队 7.4 双端队列 八、一句话记住队列 九、总结与下一篇预告)
  • [7.2 循环队列元素个数](#文章目录 【408数据结构 08】队列:循环队列判空判满,408年年考,一次讲清 @[toc] 先做个自测 一、队列到底是什么?一句话:先进先出 二、408 怎么考队列?先看真题分布 三、顺序队列:为什么需要循环? 3.1 普通顺序队列的“假溢出” 3.2 循环队列图解 四、循环队列的三种判空判满方法(408 核心) 4.1 方法一:牺牲一个存储单元(最常考) 4.2 方法二:设置 size 变量 4.3 方法三:设置 tag 标志 五、链队列:用链表实现队列 六、双端队列:408 新宠 6.1 三种双端队列 6.2 408 常考问法 6.3 双端队列的快速判断 七、真题演练 7.1 循环队列判满 7.2 循环队列元素个数 7.3 链队列出队 7.4 双端队列 八、一句话记住队列 九、总结与下一篇预告)
  • [7.3 链队列出队](#文章目录 【408数据结构 08】队列:循环队列判空判满,408年年考,一次讲清 @[toc] 先做个自测 一、队列到底是什么?一句话:先进先出 二、408 怎么考队列?先看真题分布 三、顺序队列:为什么需要循环? 3.1 普通顺序队列的“假溢出” 3.2 循环队列图解 四、循环队列的三种判空判满方法(408 核心) 4.1 方法一:牺牲一个存储单元(最常考) 4.2 方法二:设置 size 变量 4.3 方法三:设置 tag 标志 五、链队列:用链表实现队列 六、双端队列:408 新宠 6.1 三种双端队列 6.2 408 常考问法 6.3 双端队列的快速判断 七、真题演练 7.1 循环队列判满 7.2 循环队列元素个数 7.3 链队列出队 7.4 双端队列 八、一句话记住队列 九、总结与下一篇预告)
  • [7.4 双端队列](#文章目录 【408数据结构 08】队列:循环队列判空判满,408年年考,一次讲清 @[toc] 先做个自测 一、队列到底是什么?一句话:先进先出 二、408 怎么考队列?先看真题分布 三、顺序队列:为什么需要循环? 3.1 普通顺序队列的“假溢出” 3.2 循环队列图解 四、循环队列的三种判空判满方法(408 核心) 4.1 方法一:牺牲一个存储单元(最常考) 4.2 方法二:设置 size 变量 4.3 方法三:设置 tag 标志 五、链队列:用链表实现队列 六、双端队列:408 新宠 6.1 三种双端队列 6.2 408 常考问法 6.3 双端队列的快速判断 七、真题演练 7.1 循环队列判满 7.2 循环队列元素个数 7.3 链队列出队 7.4 双端队列 八、一句话记住队列 九、总结与下一篇预告)
  • [八、一句话记住队列](#文章目录 【408数据结构 08】队列:循环队列判空判满,408年年考,一次讲清 @[toc] 先做个自测 一、队列到底是什么?一句话:先进先出 二、408 怎么考队列?先看真题分布 三、顺序队列:为什么需要循环? 3.1 普通顺序队列的“假溢出” 3.2 循环队列图解 四、循环队列的三种判空判满方法(408 核心) 4.1 方法一:牺牲一个存储单元(最常考) 4.2 方法二:设置 size 变量 4.3 方法三:设置 tag 标志 五、链队列:用链表实现队列 六、双端队列:408 新宠 6.1 三种双端队列 6.2 408 常考问法 6.3 双端队列的快速判断 七、真题演练 7.1 循环队列判满 7.2 循环队列元素个数 7.3 链队列出队 7.4 双端队列 八、一句话记住队列 九、总结与下一篇预告)
  • [九、总结与下一篇预告](#文章目录 【408数据结构 08】队列:循环队列判空判满,408年年考,一次讲清 @[toc] 先做个自测 一、队列到底是什么?一句话:先进先出 二、408 怎么考队列?先看真题分布 三、顺序队列:为什么需要循环? 3.1 普通顺序队列的“假溢出” 3.2 循环队列图解 四、循环队列的三种判空判满方法(408 核心) 4.1 方法一:牺牲一个存储单元(最常考) 4.2 方法二:设置 size 变量 4.3 方法三:设置 tag 标志 五、链队列:用链表实现队列 六、双端队列:408 新宠 6.1 三种双端队列 6.2 408 常考问法 6.3 双端队列的快速判断 七、真题演练 7.1 循环队列判满 7.2 循环队列元素个数 7.3 链队列出队 7.4 双端队列 八、一句话记住队列 九、总结与下一篇预告)

先做个自测

下面这道题,你能 10 秒内选出来吗?

循环队列 Q 的 front 指向队头元素,rear 指向队尾元素的下一个位置 ,MAXSIZE 为数组容量,则队满条件是( )。

A. (Q.rear + 1) % MAXSIZE == Q.front

B. Q.rear == Q.front

C. Q.rear + 1 == Q.front

D. Q.rear == Q.front + 1

如果你犹豫了,或者分不清 front 和 rear 指向哪,那这篇就是为你写的。

队列和栈一样,是 408 选择题的常驻嘉宾 。

栈考出栈序列,队列考判空判满 。

而且队列的判空判满有三种写法,考试换一种你就容易翻车。

今天我们把队列的考点、代码、易错点一次讲透。


一、队列到底是什么?一句话:先进先出

队列(Queue)是只允许在一端插入、另一端删除的线性表。

  • 允许插入的一端叫队尾(rear)。
  • 允许删除的一端叫队头(front)。

生活里的例子:

  • 排队买票:先来的先买,后来的排后面。
  • 打印机任务:先提交的先打印。
  • 消息队列:先发送的先处理。

核心规则:

先进先出(FIFO, First In First Out)

图解:

text 复制代码
        队头 front                      队尾 rear
          |                                |
          v                                v
        +-----+-----+-----+-----+-----+
出队 <- |  1  |  2  |  3  |  4  |  5  | <- 入队
        +-----+-----+-----+-----+-----+

入队叫 enqueue,出队叫 dequeue。


二、408 怎么考队列?先看真题分布

队列在 408 中的考法非常固定:

考法 出现频率 典型问法
循环队列判空判满 ★★★★★ 给 front/rear 定义,问判空判满条件
循环队列元素个数 ★★★★★ 问队列中当前有多少元素
顺序队列假溢出 ★★★★ 为什么需要循环队列
链队列 ★★★ 链队列的插入删除
双端队列 ★★★★ 输入受限/输出受限双端队列
队列应用 ★★★★ 层序遍历、BFS、缓冲区

重点:循环队列判空判满、元素个数计算、双端队列,这三个几乎年年考。


三、顺序队列:为什么需要循环?

3.1 普通顺序队列的"假溢出"

普通顺序队列用数组存元素,front 和 rear 一直往后走:

text 复制代码
初始:
front = 0, rear = 0
+-----+-----+-----+-----+-----+
|     |     |     |     |     |
+-----+-----+-----+-----+-----+
  0     1     2     3     4

入队 1, 2, 3, 4:
front = 0, rear = 4
+-----+-----+-----+-----+-----+
|  1  |  2  |  3  |  4  |     |
+-----+-----+-----+-----+-----+
  0     1     2     3     4

出队 1, 2:
front = 2, rear = 4
+-----+-----+-----+-----+-----+
|     |     |  3  |  4  |     |
+-----+-----+-----+-----+-----+
  0     1     2     3     4

再入队 5:
front = 2, rear = 5
+-----+-----+-----+-----+-----+
|     |     |  3  |  4  |  5  |
+-----+-----+-----+-----+-----+
  0     1     2     3     4

此时 rear == MAXSIZE,但数组前面还有空位!
这就是"假溢出"。

解决办法:让 rear 和 front 走到末尾后回到开头,形成循环队列。

3.2 循环队列图解

text 复制代码
MAXSIZE = 5

        front
          |
          v
        +-----+
     +--|  3  |--+
     |  +-----+  |
     |           |
+-----+       +-----+
|  5  |       |  4  |
+-----+       +-----+
     |           |
     |  +-----+  |
     +--|     |--+
        +-----+
          ^
          |
        rear

移动公式:

text 复制代码
front = (front + 1) % MAXSIZE
rear  = (rear + 1) % MAXSIZE

四、循环队列的三种判空判满方法(408 核心)

这是 408 最爱考的地方,必须分清。

4.1 方法一:牺牲一个存储单元(最常考)

约定:

  • front 指向队头元素。
  • rear 指向队尾元素的下一个位置。
  • 空出一个位置不用,用来区分空和满。

判空:

text 复制代码
front == rear

判满:

text 复制代码
(rear + 1) % MAXSIZE == front

元素个数:

text 复制代码
(rear - front + MAXSIZE) % MAXSIZE

图解:

text 复制代码
空队列:
front = rear = 0
+-----+-----+-----+-----+-----+
|     |     |     |     |     |
+-----+-----+-----+-----+-----+
  0     1     2     3     4
  ^
  |
front/rear

满队列(牺牲一个单元):
front = 0, rear = 4
+-----+-----+-----+-----+-----+
|  1  |  2  |  3  |  4  |     |  <- 位置4空着不用
+-----+-----+-----+-----+-----+
  0     1     2     3     4
  ^                       ^
  |                       |
front                   rear

代码:

cpp 复制代码
#define MAXSIZE 100

typedef int ElemType;

typedef struct {
    ElemType data[MAXSIZE];
    int front;
    int rear;
} SqQueue;

void InitQueue(SqQueue &Q) {
    Q.front = 0;
    Q.rear = 0;
}

bool QueueEmpty(SqQueue Q) {
    return Q.front == Q.rear;
}

bool QueueFull(SqQueue Q) {
    return (Q.rear + 1) % MAXSIZE == Q.front;
}

bool EnQueue(SqQueue &Q, ElemType x) {
    if (QueueFull(Q)) {
        return false;
    }
    Q.data[Q.rear] = x;
    Q.rear = (Q.rear + 1) % MAXSIZE;
    return true;
}

bool DeQueue(SqQueue &Q, ElemType &x) {
    if (QueueEmpty(Q)) {
        return false;
    }
    x = Q.data[Q.front];
    Q.front = (Q.front + 1) % MAXSIZE;
    return true;
}

int QueueLength(SqQueue Q) {
    return (Q.rear - Q.front + MAXSIZE) % MAXSIZE;
}

记忆口诀:

front 指队头,rear 指队尾下一个。

空:front == rear。

满:(rear + 1) % MAXSIZE == front。

个数:(rear - front + MAXSIZE) % MAXSIZE。

4.2 方法二:设置 size 变量

增加一个 size 变量记录元素个数。

  • 判空:size == 0
  • 判满:size == MAXSIZE
  • 元素个数:size
cpp 复制代码
typedef struct {
    ElemType data[MAXSIZE];
    int front;
    int rear;
    int size;
} SqQueue2;

这种方法最直观,但 408 更爱考方法一。

4.3 方法三:设置 tag 标志

增加一个 tag:

  • tag = 0:最近一次是出队操作。

  • tag = 1:最近一次是入队操作。

  • 判空:front == rear && tag == 0

  • 判满:front == rear && tag == 1

cpp 复制代码
typedef struct {
    ElemType data[MAXSIZE];
    int front;
    int rear;
    int tag;
} SqQueue3;

三种方法对比:

方法 判空 判满 元素个数
牺牲一个单元 front == rear (rear+1)%MAXSIZE == front (rear-front+MAXSIZE)%MAXSIZE
设 size size == 0 size == MAXSIZE size
设 tag front==rear && tag==0 front==rear && tag==1 需另算

408 最常考方法一。


五、链队列:用链表实现队列

链队列通常用带头结点的单链表:

  • front 指向头结点。
  • rear 指向队尾结点。

图解:

text 复制代码
front                   rear
  |                       |
  v                       v
[头] -> [1] -> [2] -> [3] -> NULL
  • 入队:在 rear 后面插入新结点,rear 后移。
  • 出队:删除 front 的后继结点。

结构:

cpp 复制代码
typedef struct QNode {
    ElemType data;
    struct QNode *next;
} QNode, *QueuePtr;

typedef struct {
    QueuePtr front;
    QueuePtr rear;
} LinkQueue;

核心操作:

cpp 复制代码
// 初始化
void InitLinkQueue(LinkQueue &Q) {
    Q.front = Q.rear = new QNode;
    Q.front->next = nullptr;
}

// 判空
bool LinkQueueEmpty(LinkQueue Q) {
    return Q.front == Q.rear;
}

// 入队
void EnLinkQueue(LinkQueue &Q, ElemType x) {
    QNode *p = new QNode;
    p->data = x;
    p->next = nullptr;
    Q.rear->next = p;
    Q.rear = p;
}

// 出队
bool DeLinkQueue(LinkQueue &Q, ElemType &x) {
    if (LinkQueueEmpty(Q)) {
        return false;
    }
    QNode *p = Q.front->next;
    x = p->data;
    Q.front->next = p->next;
    if (Q.rear == p) {
        Q.rear = Q.front;  // 队列变空
    }
    delete p;
    return true;
}

链队列的坑:

出队时,如果删除的是最后一个结点,必须把 rear 重新指向头结点。

否则 rear 会变成野指针。

408 常考:

链队列出队时,什么情况下需要修改 rear 指针?

答:当出队的是队列中最后一个元素时。


六、双端队列:408 新宠

双端队列(Deque)允许两端都可以插入和删除。

6.1 三种双端队列

类型 特点
普通双端队列 两端都可以入队和出队
输入受限双端队列 只允许一端插入,两端都可以删除
输出受限双端队列 只允许一端删除,两端都可以插入

图解:

text 复制代码
普通双端队列:
入队/出队 <-- [ | | | | ] --> 入队/出队

输入受限:
只允许一端入队 <-- [ | | | | ] --> 两端都能出队

输出受限:
两端都能入队 <-- [ | | | | ] --> 只允许一端出队

6.2 408 常考问法

输入受限双端队列,入队序列为 1, 2, 3, 4,哪些出队序列不可能?

这类题用模拟法,和栈的出栈序列类似。

例题:

输入受限双端队列(只允许一端入队,两端都可以出队),入队序列为 1, 2, 3, 4,则哪个出队序列不可能?

A. 1, 2, 3, 4

B. 4, 3, 2, 1

C. 2, 4, 3, 1

D. 3, 1, 2, 4

答案:D

解析:3, 1, 2, 4 中,3 出队后,1 和 2 在队列中,1 在 2 前面(因为只能一端入队),所以不可能先出 1 再出 2。

6.3 双端队列的快速判断

对于输入受限双端队列,合法出队序列的充要条件:

不存在三个下标 i < j < k,使得出队序列中 a[k] < a[i] < a[j]。

这和栈的出栈序列判断类似,但双端队列更灵活。


七、真题演练

7.1 循环队列判满

题目:

循环队列 Q 的 front 指向队头元素,rear 指向队尾元素的下一个位置,MAXSIZE 为数组容量,则队满条件是( )。

A. (Q.rear + 1) % MAXSIZE == Q.front

B. Q.rear == Q.front

C. Q.rear + 1 == Q.front

D. Q.rear == Q.front + 1

答案:A

7.2 循环队列元素个数

题目:

循环队列 Q 的 front 指向队头元素,rear 指向队尾元素的下一个位置,MAXSIZE 为数组容量,则队列中元素个数是( )。

A. Q.rear - Q.front

B. Q.rear - Q.front + MAXSIZE

C. (Q.rear - Q.front + MAXSIZE) % MAXSIZE

D. (Q.rear - Q.front) % MAXSIZE

答案:C

7.3 链队列出队

题目:

链队列出队时,什么情况下需要修改 rear 指针?

A. 队列为空时

B. 出队的是最后一个元素时

C. 出队的是第一个元素时

D. 任何时候都不需要

答案:B

7.4 双端队列

题目:

输入受限双端队列,入队序列为 1, 2, 3,则可能的出队序列有多少种?

A. 3

B. 4

C. 5

D. 6

答案:C

解析:可能的出队序列有:1,2,3、3,2,1、2,3,1、2,1,3、1,3,2,共 5 种。


八、一句话记住队列

队列先进先出,循环队列牺牲一个单元,空看 frontrear,满看 (rear+1)%MAXSIZEfront,个数看 (rear-front+MAXSIZE)%MAXSIZE,链队列出队最后一个要改 rear。


九、总结与下一篇预告

本篇讲了:

  • 队列的定义与先进先出特性。
  • 顺序队列的假溢出问题。
  • 循环队列的三种判空判满方法。
  • 循环队列元素个数计算。
  • 链队列的实现与出队坑点。
  • 双端队列的三种类型与判断方法。
  • 408 真题与易错点。

下一篇进入栈和队列的应用:

【408数据结构 09】栈和队列应用:括号匹配、表达式求值、递归

我会讲括号匹配、中缀转后缀、表达式求值、递归与栈的关系、层序遍历,配 408 真题和完整 C++ 代码。


专栏导航

  • 上一篇:【408数据结构 07】栈:408每年必考,这3个坑90%的人会踩
  • 下一篇:【408数据结构 09】栈和队列应用:括号匹配、表达式求值、递归
  • 专栏目录:《408数据结构:C++手写实现 + 图解 + 真题》

标签 :数据结构、C++、考研408、计算机考研、算法

分类:数据结构与算法

如果这篇对你有帮助,欢迎点赞、收藏、评论。你的支持是我持续更新的动力。

相关推荐
谢亮_vipxieliang2 分钟前
Go 接口设计原则核心知识点
开发语言·ios·golang
Logic1013 分钟前
C语言/数据结构位运算题解:异或XOR找出英雄队伍中的“独特战斗力“——只出现一次的数字
c语言·数据结构·数组·位运算·时间复杂度·算法题·异或性质
Wang's Blog3 分钟前
Java框架 SpringCloud 快速入门: Feign 替代 RestTemplate 实现声明式远程调用
java·开发语言·spring cloud
谢亮_vipxieliang3 分钟前
Go 结构体与方法集核心知识点
java·开发语言·golang
ra90fy5 分钟前
B3873 [GESP202309 六级] 小杨买饮料
c++·算法
郝学胜-神的一滴6 分钟前
Numpy数据处理详解 01:NumPy 从环境搭建到入门上手
开发语言·人工智能·python·程序人生·数据分析·numpy
尘客-追梦7 分钟前
qmake / jom / 影子构建:把编译管起来
开发语言·c++·qt
Ai-_Man10 分钟前
从聊天框到正式文档:AI导出鸭瞄准AI大模型应用的“最后一公里”
开发语言·前端·javascript·人工智能·小程序
EatFan11 分钟前
2026 Java 后端面试风向变了:八股文只是门槛,场景化追问才是淘汰线
java·开发语言·jvm·面试·后端面试·八股文·full gc
Omics Pro14 分钟前
北理工李荣华:AI虚拟细胞证据多模态推理基准
数据库·人工智能·算法·机器学习·自然语言处理