当前位置: 首页 > news >正文

【软考中级 - 软件设计师 - 基础知识】数据结构之栈与队列​

栈和队列是 “受限的线性表”—— 它们在 linear 表的基础上增加了 “操作规则”,是算法设计和实际开发中最常用的结构(比如函数调用用栈、消息排队用队列)。考试中二者常结合 “操作顺序判断”“存储实现缺陷”“场景匹配” 出题,核心是掌握 “规则差异 + 关键操作”,下文分模块拆解。​

一、先分清:栈与队列的核心规则(必记)​

栈和队列的本质区别是 “元素进出的顺序规则”,用生活例子就能轻松记住:​

数据结构​

核心规则​

生活例子​

关键操作(考试重点)​

栈​

先进后出(LIFO)​

叠盘子:先放的盘子在下面,后拿​

入栈(push)、出栈(pop)​

队列​

先进先出(FIFO)​

排队买票:先到的人先买​

入队(enqueue)、出队(dequeue)​

直观对比:​

  • 栈:比如浏览器 “后退” 功能 —— 先打开的页面(A→B→C),后退时先退 C,再退 B,最后退 A(符合先进后出);​
  • 队列:比如打印机 “排队打印”—— 先提交的文档(1→2→3),先打印 1,再打印 2,最后打印 3(符合先进先出)。​

二、核心考点 1:栈的存储与核心操作​

栈的存储分 “顺序存储(数组)” 和 “链式存储(链表)”,考试重点考顺序存储(占比 80%),需掌握 “栈满 / 栈空判断” 和 “push/pop 操作步骤”。​

1. 顺序存储(数组实现)​

用数组存栈元素,额外用一个 “栈顶指针(top)” 记录栈顶位置(top 初始为 - 1,代表栈空):​

  • 栈空条件:top == -1;​
  • 栈满条件:top == 数组长度 - 1(比如数组长度为 5,top=4 时栈满)。​
(1)入栈(push):往栈顶加元素​

步骤(数组长度 5,初始栈空 top=-1,入栈元素 1、2、3):​

Step1:判断是否栈满(若 top==4,报错 “栈满”);​

Step2:top+1(top 从 - 1→0);​

Step3:把元素放到数组 [top] 位置(数组 [0]=1);​

重复 Step1-Step3,依次入栈 2、3:​

  • 入栈 2 后:top=1,数组 [1]=2;​
  • 入栈 3 后:top=2,数组 [2]=3;​

最终栈内元素:[1,2,3](栈顶是 3)。​

(2)出栈(pop):从栈顶拿元素​

步骤(接上面的栈,出栈 2 次):​

Step1:判断是否栈空(若 top==-1,报错 “栈空”);​

Step2:取出数组 [top] 的元素(第一次取数组 [2]=3);​

Step3:top-1(top 从 2→1);​

重复 Step1-Step3,第二次出栈:​

  • 取出数组 [1]=2,top 从 1→0;​

最终栈内剩余元素:[1](栈顶是 1)。​

易错提醒:​

  • 顺序栈 “栈满后不能再入栈”,若要继续存元素,需 “扩容”(考试一般不考扩容细节,知道要扩容即可);​
  • 出栈只能拿栈顶元素,不能直接拿中间元素(比如上面的栈,不能直接取出 1,必须先出栈 3、2)。​

2. 链式存储(链表实现)​

用链表存栈元素,栈顶就是链表的 “头节点”(不用遍历,直接操作头节点,效率高):​

  • 栈空条件:头节点为 null;​
  • 入栈:新节点作为新头节点(新节点.next = 原头节点);​
  • 出栈:删除头节点,新头节点 = 原头节点.next;​

例子:入栈 1→2→3,链表结构为:3(头节点)→2→1→null;​

出栈 1 次:删除头节点 3,新头节点 = 2,链表变为 2→1→null。​

适用场景:​

顺序栈适合 “元素个数固定” 的场景(比如函数调用栈),链式栈适合 “元素个数不确定” 的场景(比如动态添加的任务栈)。​

3. 栈的典型应用场景(真题高频)​

应用场景​

原理(先进后出)​

例子​

表达式求值​

用栈存运算符,优先级高的先计算​

计算 “3+42”:先算 42,再算 3+8​

函数调用栈​

调用函数时入栈,函数返回时出栈​

主函数调用 A,A 调用 B→B 返回后 A 再返回主函数​

浏览器后退 / 编辑器撤销​

每打开新页面 / 输入内容时入栈,后退 / 撤销时出栈​

浏览器打开 A→B→C,后退先退 C​

三、核心考点 2:队列的存储与核心操作​

队列的存储也分 “顺序存储” 和 “链式存储”,但顺序存储有 “假溢出” 问题,需用 “循环队列” 解决(考试重点考循环队列)。​

1. 顺序存储的问题:假溢出​

普通顺序队列用数组 +“队头指针(front)”“队尾指针(rear)” 实现:​

  • 队空条件:front == rear(初始都为 0);​
  • 入队:rear+1,数组 [rear] 存元素;​
  • 出队:front+1,取出数组 [front] 元素;​

假溢出问题:比如数组长度 5,入队 1、2、3、4(rear=4),出队 1、2(front=2),此时数组还有 [3,4],但 rear=4 已到数组末尾,无法再入队 5(实际数组 [0,1] 是空的)—— 这就是 “假溢出”(明明有空间,却提示队满)。​

2. 循环队列:解决假溢出(考试重点)​

把数组 “首尾相连”,形成循环(rear 到数组末尾后,再从 0 开始),用 “取余(%)” 实现循环逻辑:​

  • 数组长度记为 maxSize;​
  • 队空条件:front == rear;​
  • 队满条件:(rear + 1) % maxSize == front(故意空一个位置,避免和队空混淆);​
  • 元素个数:(rear - front + maxSize) % maxSize(加 maxSize 是为了避免 rear<front 时出现负数)。​
(1)入队(enqueue):循环队列存元素​

步骤(maxSize=5,初始 front=0,rear=0,入队 1、2、3):​

Step1:判断是否队满((rear+1)%5 == front?初始 rear=0,(0+1)%5=1≠0,不队满);​

Step2:rear = (rear + 1) % 5(rear 从 0→1);​

Step3:数组 [rear] = 元素(数组 [1]=1);​

重复 Step1-Step3,入队 2、3:​

  • 入队 2 后:rear=(1+1)%5=2,数组 [2]=2;​
  • 入队 3 后:rear=(2+1)%5=3,数组 [3]=3;​

此时队列元素:[,1,2,3,](front=0,rear=3)。​

(2)出队(dequeue):循环队列取元素​

步骤(接上面的队列,出队 2 次):​

Step1:判断是否队空(front==rear?0≠3,不队空);​

Step2:front = (front + 1) % 5(front 从 0→1);​

Step3:取出数组 [front] 的元素(第一次取数组 [1]=1);​

重复 Step1-Step3,第二次出队:​

  • front=(1+1)%5=2,取出数组 [2]=2;​

此时队列元素:[, ,3,](front=2,rear=3),元素个数 =(3-2+5)%5=1。​

关键计算(真题常考):​

若循环队列 maxSize=6,front=4,rear=1,求元素个数:​

元素个数 =(1-4+6)%6=3(队列里有 3 个元素)。​

3. 链式存储(链表实现)​

用链表存队列元素,队头是链表 “头节点”(出队快),队尾是链表 “尾节点”(入队快):​

  • 队空条件:头节点 ==null;​
  • 入队:新节点接在尾节点后,更新尾节点;​
  • 出队:删除头节点,更新头节点;​

例子:入队 1→2→3,链表结构:头节点 1→2→尾节点 3;​

出队 1 次:删除头节点 1,新头节点 = 2,链表变为 2→3(尾节点不变)。​

适用场景:​

循环队列适合 “元素个数固定” 的场景(比如固定大小的任务队列),链式队列适合 “元素个数不确定” 的场景(比如消息队列)。​

4. 队列的典型应用场景(真题高频)​

应用场景​

原理(先进先出)​

例子​

消息队列​

先发送的消息先处理​

用户发送的聊天消息,按顺序显示​

任务调度​

先提交的任务先执行​

服务器处理用户请求,按请求顺序执行​

缓冲区(如打印机)​

先提交的打印任务先打印​

多用户提交打印,队列排序​

四、高频考点对比:栈与队列的核心差异​

考试常考 “操作顺序判断”,比如 “元素入栈 / 入队顺序为 1,2,3,可能的出栈 / 出队顺序是什么”,核心是记住规则差异:​

对比维度​

栈(先进后出)​

队列(先进先出)​

操作顺序判断​

出栈顺序不唯一(比如入栈 1,2,3,出栈可 3,2,1 或 2,3,1)​

出队顺序唯一(入队 1,2,3,出队只能 1,2,3)​

存储关键问题​

顺序栈:栈满扩容​

顺序队列:假溢出(需循环队列解决)​

指针作用​

仅栈顶指针(top)​

队头(front)+ 队尾(rear)指针​

真题示例:​

判断 “入栈顺序为 1,2,3,4,出栈顺序为 3,4,2,1” 是否合法?​

分析:1 入→2 入→3 入→3 出→4 入→4 出→2 出→1 出,符合先进后出,合法。​

五、备考小贴士(3 步搞定)​

  1. 记规则:栈 “先进后出”、队列 “先进先出”,用生活例子(叠盘子、排队)辅助记忆;​
  2. 练操作:重点练循环队列的 “队满 / 队空判断” 和 “元素个数计算”(比如 maxSize=5,front=3,rear=1,元素个数 =(1-3+5)%5=3);​
  3. 场景对应:看到 “后退 / 撤销 / 函数调用” 选栈,看到 “消息 / 任务 / 排队” 选队列,不用想复杂。​

下一篇【基础知识】专栏将讲解 “树结构基础”(二叉树的定义、遍历),树是 “非线性结构” 的入门,和栈、队列关联紧密(比如二叉树遍历用栈或队列实现),建议提前回顾栈和队列的操作逻辑。

http://www.dtcms.com/a/394909.html

相关文章:

  • LeetCode 385 迷你语法分析器 Swift 题解:从字符串到嵌套数据结构的解析过程
  • windows系统使用sdkman管理java的jdk版本,WSL和Git Bash哪个更能方便管理jdk版本
  • 生产环境K8S的etcd备份脚本
  • Mac电脑多平台Git账号配置
  • Etcd详解:Kubernetes的大脑与记忆库
  • 深刻理解PyTorch中RNN(循环神经网络)的output和hn
  • 大模型如何赋能写作:从创作到 MCP 自动发布的全链路解析
  • C++设计模式之创建型模式:工厂方法模式(Factory Method)
  • 传输层协议——UDP/TCP
  • 三板汇茶咖空间签约“可信资产IPO与数链金融RWA”链改2.0项目联合实验室
  • 【MySQL】MySQL 表文件误删导致启动失败及无法外部连接解决方案
  • LVS简介
  • 如何将联系人从iPhone转移到iPhone的7种方法
  • 『 MySQL数据库 』MySQL复习(一)
  • 3005. 最大频率元素计数
  • ACP(七)优化RAG应用提升问答准确度
  • 鸿蒙:使用bindPopup实现气泡弹窗
  • Langchan4j 框架 AI 无限循环调用文件创建工具解决方案记录
  • Python GIS 开发里最核心的4个基础组件(理论+实操篇)
  • 关于跨域和解决方案
  • 学习日报 20250921|LoadingCache
  • 聚力赋能|竹云受邀出席2025华为全联接大会
  • 抓取 Dump 文件与 WinDbg 使用详解:定位 Windows 程序异常的利器
  • 计算机组成原理:指令周期
  • 老题新解|简单算术表达式求值
  • RustFS与其他新兴存储系统(如SeaweedFS)相比有哪些优势和劣势?
  • WPS标点符号换行问题解决
  • 开发团队的文档自动化革命:WPS+cpolar实战录
  • 【Linux】文本编辑器Vim
  • flink1.18下游配置多个sink