数据结构——栈与队列:原理、实现与经典应用
上一篇讲了线性表顺序表和链表这一篇讲线性表的两种特殊形式——栈Stack和队列Queue。它们在 408 考研和面试中出现频率极高。一、栈——后进先出1. 什么是栈栈Stack是限定只能在一端进行插入和删除操作的线性表。允许操作的一端 → 栈顶Top 不允许操作的一端 → 栈底Bottom 插入 → 入栈Push 删除 → 出栈Pop ← 出栈 ┌───┐ │ 5 │ ← 栈顶 ├───┤ │ 4 │ ├───┤ │ 3 │ ├───┤ │ 2 │ ├───┤ │ 1 │ ← 栈底 └───┘ push(6) → 放到栈顶特点后进先出LIFO, Last In First Out生活中的例子一叠盘子——你只能从上面拿后放上去的先用浏览器的后退——最后访问的页面最先回退函数调用——最里层的函数最先返回2. 顺序栈数组实现publicclassArrayStackE{privatestaticfinalintDEFAULT_CAPACITY10;privateE[]data;privateinttop;// 栈顶指针指向当前栈顶元素位置publicArrayStack(){data(E[])newObject[DEFAULT_CAPACITY];top-1;// 初始为空栈}// 入栈publicvoidpush(Eelement){if(topdata.length-1){grow();// 扩容}data[top]element;}// 出栈publicEpop(){if(isEmpty())thrownewEmptyStackException();Eelementdata[top];data[top--]null;// 清空引用帮助 GCreturnelement;}// 查看栈顶不删除publicEpeek(){if(isEmpty())thrownewEmptyStackException();returndata[top];}publicbooleanisEmpty(){returntop-1;}publicintsize(){returntop1;}}时间复杂度push/pop/peek 都是O(1)。3. 链栈链表实现publicclassLinkedStackE{privateNodeEtop;// 栈顶链表头privateintsize;privatestaticclassNodeE{Edata;NodeEnext;Node(Edata){this.datadata;}}publicvoidpush(Eelement){NodeEnewNodenewNode(element);newNode.nexttop;// 新节点指向旧栈顶topnewNode;// 新节点成为栈顶size;}publicEpop(){if(isEmpty())thrownewEmptyStackException();Edatatop.data;toptop.next;// 栈顶下移size--;returndata;}publicEpeek(){if(isEmpty())thrownewEmptyStackException();returntop.data;}publicbooleanisEmpty(){returntopnull;}}注意链栈的 push/pop 都是在链表头部操作不需要遍历时间复杂度O(1)。二、队列——先进先出1. 什么是队列队列Queue是限定在一端插入、另一端删除的线性表。插入队尾→ ┌───┬───┬───┬───┬───┐ → 删除队头 │ 1 │ 2 │ 3 │ 4 │ 5 │ └───┴───┴───┴───┴───┘ front ↑ ↑ rear特点先进先出FIFO, First In First Out生活中的例子排队买奶茶——先来的先买到打印机任务队列——先提交的先打印消息队列——生产者发送消费者按顺序处理2. 顺序队列的问题// 直接使用数组实现队列的问题// 出队时 front 后移导致数组前面的空间被浪费初始 front0,rear0[][][][][]A入队[A][][][][]B入队[A][B][][][]A出队 front1[][B][][][]← 下标0的空间浪费了解决方案循环队列3. 循环队列┌──────────────────────┐ │ rear │ │ ↓ │ │ ┌──┬──┬──┬──┬──┐ │ │ │ │ │E │F │G │ │ │ ├──┼──┼──┼──┼──┤ │ │ │D │ │ │ │ │ │ │ └──┴──┴──┴──┴──┘ │ │ ↑ │ │ front │ └──────────────────────┘publicclassCircularQueueE{privateE[]data;privateintfront;// 队头指针privateintrear;// 队尾指针指向下一个插入位置privateintsize;privateintcapacity;publicCircularQueue(intcapacity){this.capacitycapacity;data(E[])newObject[capacity];front0;rear0;size0;}// 入队publicbooleanenqueue(Eelement){if(isFull())returnfalse;data[rear]element;rear(rear1)%capacity;// 循环size;returntrue;}// 出队publicEdequeue(){if(isEmpty())returnnull;Eelementdata[front];data[front]null;front(front1)%capacity;// 循环size--;returnelement;}publicbooleanisEmpty(){returnsize0;}publicbooleanisFull(){returnsizecapacity;}}关键rear (rear 1) % capacity实现循环——到达数组末尾后回到开头。4. 链式队列publicclassLinkedQueueE{privateNodeEfront;// 队头出队privateNodeErear;// 队尾入队privateintsize;publicvoidenqueue(Eelement){NodeEnewNodenewNode(element);if(isEmpty()){frontrearnewNode;}else{rear.nextnewNode;rearnewNode;}size;}publicEdequeue(){if(isEmpty())returnnull;Edatafront.data;frontfront.next;if(frontnull)rearnull;// 队列变空size--;returndata;}}三、栈和队列的对比对比栈队列规则后进先出LIFO先进先出FIFO插入/删除位置同一端栈顶两端队尾/队头常用实现数组顺序栈循环数组循环队列适用场景递归转非递归、括号匹配排队系统、BFS、消息队列四、408 考研经典考题题1括号匹配publicbooleanisValid(Strings){StackCharacterstacknewStack();for(charc:s.toCharArray()){if(c(||c[||c{){stack.push(c);// 左括号入栈}else{if(stack.isEmpty())returnfalse;chartopstack.pop();if(c)top!()returnfalse;if(c]top![)returnfalse;if(c}top!{)returnfalse;}}returnstack.isEmpty();// 所有左括号都匹配完}题2用两个栈实现队列classMyQueue{privateStackIntegerinStack;// 入队栈privateStackIntegeroutStack;// 出队栈publicMyQueue(){inStacknewStack();outStacknewStack();}publicvoidpush(intx){inStack.push(x);// 直接压入入队栈}publicintpop(){if(outStack.isEmpty()){// 把入队栈的元素全部倒入出队栈while(!inStack.isEmpty()){outStack.push(inStack.pop());}}returnoutStack.pop();}}原理入队时放入 inStack出队时从 outStack 取。outStack 空了就把 inStack 全部倒过来——倒一次后元素的顺序就变成了队列顺序。题3循环队列判空判满两种判断方式 方法1size 字段推荐简单明了 isEmpty() → size 0 isFull() → size capacity 方法2牺牲一个存储单元 空 → rear front 满 → (rear 1) % capacity front题4用队列实现栈了解即可classMyStack{privateQueueIntegerqueue;publicvoidpush(intx){queue.offer(x);// 把前面的元素移到后面让新元素在队头for(inti0;iqueue.size()-1;i){queue.offer(queue.poll());}}publicintpop(){returnqueue.poll();}}五、实际开发中的应用栈的应用 JVM 虚拟机栈 → 方法调用和返回 表达式求值 → 中缀转后缀 撤销操作 → CtrlZ 队列的应用 线程池任务队列 → 等待执行的任务 消息队列 MQ → 异步解耦 树的层序遍历 → BFS六、Java 中的栈和队列// 栈Java 官方推荐用 Deque 代替 StackDequeStringstacknewArrayDeque();stack.push(A);// 入栈stack.pop();// 出栈stack.peek();// 查看栈顶// 队列QueueStringqueuenewLinkedList();queue.offer(A);// 入队queue.poll();// 出队queue.peek();// 查看队头// 双端队列两端都可操作DequeStringdequenewArrayDeque();deque.addFirst(A);deque.addLast(B);deque.removeFirst();deque.removeLast();总结栈和队列其实就是限制了操作位置的线性表。栈只在一端操作LIFO队列在两端操作FIFO。代码实现时注意循环队列的取模运算和判空判满条件。 觉得有用的话点赞 关注【张老师技术栈】吧每周更新 Java/Python/爬虫 实战干货不让你白来。

相关新闻

ComfyUI-WanVideoWrapper Block Swap技术深度解析:实现40% VRAM优化突破

ComfyUI-WanVideoWrapper Block Swap技术深度解析:实现40% VRAM优化突破

ComfyUI-WanVideoWrapper Block Swap技术深度解析:实现40% VRAM优化突破 【免费下载链接】ComfyUI-WanVideoWrapper 项目地址: https://gitcode.com/GitHub_Trending/co/ComfyUI-WanVideoWrapper ComfyUI-WanVideoWrapper作为WanVideo模型在ComfyUI平台的创…

2026/7/3 0:58:10 阅读更多 →
5.7万 Star!GitHub 爆火的 AI 求职神器

5.7万 Star!GitHub 爆火的 AI 求职神器

大家好,我是Java1234_小锋老师。 一、为什么它能火? 最近 GitHub 上有一个项目格外引人注目——Career-Ops,Star 数已经突破 5.7 万。 说实话,求职类工具并不少见。但 Career-Ops 能在一众项目中脱颖而出,原因其实挺…

2026/7/3 0:58:10 阅读更多 →
【BUG已解决】macOS zsh: command not found: python 解决方案

【BUG已解决】macOS zsh: command not found: python 解决方案

【BUG已解决】macOS zsh: command not found: python 解决方案 1. 问题描述 在 macOS 终端中输入 python 命令,系统报错: $ python zsh: command not found: python但是执行 python3 却能正常工作: $ python3 Python 3.11.5 (main, ...) on d…

2026/7/3 0:56:09 阅读更多 →

最新新闻

手把手教你用OpenCV和YOLO搭建实时目标检测系统(毕设实战)

手把手教你用OpenCV和YOLO搭建实时目标检测系统(毕设实战)

临近毕业季,很多计算机、电子信息、人工智能相关专业的同学都在为毕设选题和实现发愁。特别是计算机视觉方向,听起来高大上,但面对复杂的算法、庞大的代码库和繁琐的环境配置,往往让人望而却步。如果你也正为“基于深度学习的XX检…

2026/7/3 1:56:19 阅读更多 →
直流电机静音控制方案:H桥驱动与PID算法实践

直流电机静音控制方案:H桥驱动与PID算法实践

1. 项目背景与核心器件选型在工业自动化和消费电子领域,直流电机控制一直是个经典课题。传统PWM调速方案虽然成本低廉,但开关噪声问题始终困扰着对声学敏感的应用场景。这次我们选用东芝的TB9051FTG驱动芯片搭配Microchip的PIC18F46K20 MCU,构…

2026/7/3 1:54:19 阅读更多 →
Home Assistant Operating System终极方案:如何构建专业级智能家居操作系统?

Home Assistant Operating System终极方案:如何构建专业级智能家居操作系统?

Home Assistant Operating System终极方案:如何构建专业级智能家居操作系统? 【免费下载链接】operating-system :beginner: Home Assistant Operating System 项目地址: https://gitcode.com/gh_mirrors/op/operating-system Home Assistant Ope…

2026/7/3 1:54:19 阅读更多 →
股票研究信息处理:AI工具在资讯、财报与复盘环节的辅助作用

股票研究信息处理:AI工具在资讯、财报与复盘环节的辅助作用

普通投资者做股票研究时,最容易陷入信息过载与流程混乱:每天要刷大量资讯、读研报、翻财报,还要做盯盘记录与复盘总结,零散的信息很难沉淀成体系,反复查找资料又浪费大量时间。我实际用下来,AI工具的核心价…

2026/7/3 1:52:19 阅读更多 →
Tokio 背压:异步不是无限接请求的许可证

Tokio 背压:异步不是无限接请求的许可证

Tokio 背压:异步不是无限接请求的许可证 Tokio 让 Rust 服务能优雅处理大量连接,但异步不是无限接请求的许可证。没有背压的异步系统,会把压力藏进 channel、任务队列、buffer 和下游连接池里。表面上线程没阻塞,实际内存和尾延迟…

2026/7/3 1:52:19 阅读更多 →
Prometheus 记录规则:查询快了,语义也要清楚

Prometheus 记录规则:查询快了,语义也要清楚

Prometheus 记录规则:查询快了,语义也要清楚 一、记录规则不是为了偷懒写短查询 Prometheus 查询复杂时,很多团队会用 recording rules 把中间结果预计算出来。这样能减少查询压力,也能让告警表达更清晰。但记录规则不是为了偷懒把…

2026/7/3 1:52:19 阅读更多 →

日新闻

Nginx防御TLS重协商攻击实战:从原理到配置与监控

Nginx防御TLS重协商攻击实战:从原理到配置与监控

1. 项目概述:为什么TLS重协商攻击至今仍需警惕十多年前的CVE-2011-1473,一个关于TLS/SSL协议重协商机制的漏洞,现在提起来还有必要吗?很多运维和开发朋友可能会觉得,这都老掉牙了,现代服务器和客户端不都默…

2026/7/3 0:03:59 阅读更多 →
华为防火墙双通道远程管理实战:Web与SSH配置详解

华为防火墙双通道远程管理实战:Web与SSH配置详解

1. 项目概述:为什么需要双通道远程管理防火墙?在任何一个稍具规模的企业网络里,防火墙都是那个默默守护在边界的关键角色。作为网络工程师,我们不可能每次都跑到机房,插上console线去配置它。远程管理能力,…

2026/7/3 0:03:59 阅读更多 →
AD74413R与PIC18F65K40的高精度工业数据采集方案

AD74413R与PIC18F65K40的高精度工业数据采集方案

1. 项目概述:AD74413R与PIC18F65K40的协同工作在工业自动化和精密测量领域,同时实现高精度模数转换(ADC)和数模转换(DAC)功能是许多复杂系统的核心需求。AD74413R作为一款四通道可配置模拟输入/输出器件,与PIC18F65K40微控制器的组合&#xf…

2026/7/3 0:05:59 阅读更多 →

周新闻

月新闻