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

栈(Stack)核心概念

栈(Stack)核心概念

什么是栈?

栈是一种**后进先出(LIFO - Last In First Out)**的线性数据结构。想象一摞盘子,你只能从顶部放盘子,也只能从顶部取盘子。

栈的核心操作

操作说明时间复杂度
push()入栈(添加元素到栈顶)O(1)
pop()出栈(移除并返回栈顶元素)O(1)
peek()查看栈顶元素(不移除)O(1)
isEmpty()判断栈是否为空O(1)
size()获取栈中元素个数O(1)

图解:栈的工作流程

初始状态:空栈 ┌─────────┐ │ │ ← 栈顶 (Top) └─────────┘ push(10): ┌─────────┐ │ 10 │ ← 栈顶 └─────────┘ push(20): ┌─────────┐ │ 20 │ ← 栈顶 ├─────────┤ │ 10 │ └─────────┘ push(30): ┌─────────┐ │ 30 │ ← 栈顶 ├─────────┤ │ 20 │ ├─────────┤ │ 10 │ └─────────┘ pop() → 返回 30: ┌─────────┐ │ 20 │ ← 栈顶 ├─────────┤ │ 10 │ └─────────┘ peek() → 返回 20 (不移除): ┌─────────┐ │ 20 │ ← 栈顶 ├─────────┤ │ 10 │ └─────────┘

Java 实现栈的三种方式

方式一:基于数组实现(手动实现)

publicclassArrayStack<T>{privateObject[]elements;privateinttop;// 栈顶指针privateintcapacity;// 容量publicArrayStack(intcapacity){this.capacity=capacity;this.elements=newObject[capacity];this.top=-1;// -1 表示空栈}// 入栈publicvoidpush(Titem){if(isFull()){thrownewRuntimeException("栈已满");}elements[++top]=item;}// 出栈@SuppressWarnings("unchecked")publicTpop(){if(isEmpty()){thrownewRuntimeException("栈为空");}Titem=(T)elements[top];elements[top--]=null;// 防止内存泄漏returnitem;}// 查看栈顶@SuppressWarnings("unchecked")publicTpeek(){if(isEmpty()){thrownewRuntimeException("栈为空");}return(T)elements[top];}publicbooleanisEmpty(){returntop==-1;}publicbooleanisFull(){returntop==capacity-1;}publicintsize(){returntop+1;}// 测试publicstaticvoidmain(String[]args){ArrayStack<Integer>stack=newArrayStack<>(5);System.out.println("=== 入栈操作 ===");stack.push(10);stack.push(20);stack.push(30);System.out.println("栈大小: "+stack.size());// 3System.out.println("\n=== 查看栈顶 ===");System.out.println("栈顶元素: "+stack.peek());// 30System.out.println("\n=== 出栈操作 ===");while(!stack.isEmpty()){System.out.println("弹出: "+stack.pop());// 30, 20, 10}}}

方式二:基于链表实现(动态扩容)

publicclassLinkedStack<T>{privatestaticclassNode<T>{Tdata;Node<T>next;Node(Tdata){this.data=data;}}privateNode<T>top;// 栈顶节点privateintsize;// 入栈(头插法)publicvoidpush(Titem){Node<T>newNode=newNode<>(item);newNode.next=top;top=newNode;size++;}// 出栈publicTpop(){if(isEmpty()){thrownewRuntimeException("栈为空");}Tdata=top.data;top=top.next;size--;returndata;}publicTpeek(){if(isEmpty()){thrownewRuntimeException("栈为空");}returntop.data;}publicbooleanisEmpty(){returntop==null;}publicintsize(){returnsize;}}

方式三:使用 Java 内置 Stack 类(不推荐用于新项目)

importjava.util.Stack;publicclassBuiltInStackDemo{publicstaticvoidmain(String[]args){Stack<String>stack=newStack<>();// 入栈stack.push("Java");stack.push("Python");stack.push("Go");// 出栈while(!stack.isEmpty()){System.out.println(stack.pop());// Go, Python, Java}}}

⚠️注意java.util.Stack是遗留类,官方推荐使用Deque接口的实现类(如ArrayDeque)代替。

推荐方式:使用 ArrayDeque(现代 Java 最佳实践)

importjava.util.ArrayDeque;importjava.util.Deque;publicclassModernStackDemo{publicstaticvoidmain(String[]args){// Deque 作为栈使用(官方推荐)Deque<Integer>stack=newArrayDeque<>();// 入栈stack.push(100);stack.push(200);stack.push(300);System.out.println("栈顶: "+stack.peek());// 300// 出栈while(!stack.isEmpty()){System.out.println("弹出: "+stack.pop());// 300, 200, 100}}}

栈的应用场景

应用场景说明
函数调用方法调用的执行上下文保存在调用栈中
表达式求值中缀表达式转后缀表达式、计算器实现
括号匹配编译器检查代码括号是否配对
浏览器前进/后退浏览历史记录管理
撤销操作编辑器 Ctrl+Z 功能
DFS 算法深度优先搜索的非递归实现

经典例题:括号匹配检测

publicclassBracketMatch{publicstaticbooleanisValid(Strings){Deque<Character>stack=newArrayDeque<>();for(charc:s.toCharArray()){if(c=='('||c=='['||c=='{'){stack.push(c);}else{if(stack.isEmpty())returnfalse;chartop=stack.pop();if((c==')'&&top!='(')||(c==']'&&top!='[')||(c=='}'&&top!='{')){returnfalse;}}}returnstack.isEmpty();}publicstaticvoidmain(String[]args){System.out.println(isValid("()"));// trueSystem.out.println(isValid("()[]{}"));// trueSystem.out.println(isValid("(]"));// falseSystem.out.println(isValid("([)]"));// false}}

总结对比

实现方式优点缺点适用场景
数组实现访问快,内存局部性好固定容量,可能溢出已知最大容量
链表实现动态扩容,无容量限制额外指针开销容量不确定
ArrayDeque高效、官方推荐、无锁首选方案

栈是最基础且重要的数据结构之一,掌握它的原理和实现对于理解递归、算法设计都至关重要!

http://www.cnnetsun.cn/news/1560931.html

相关文章:

  • Kubernetes资源监控与告警:从指标到行动的完整闭环
  • LeetCode 399. Evaluate Division 题解
  • 如何通过梯度累积步数优化显存受限下的训练批次大小?
  • 最近在研究COMSOL的瓦斯抽采数值模拟,发现这玩意儿真的挺有意思。尤其是煤体变形和瓦斯抽采的耦合问题,简直是个大坑,但跳进去之后发现还挺有挑战性的
  • vscode连接ssh后codex登录问题
  • Pandas第二章 基础
  • openGauss数据库设计实战:PowerDesigner E-R建模与正向工程全解析
  • 离散状态观测器
  • 安装ROS2,亲测有效
  • FlashAI:推动AI技术民主化的零门槛部署方案
  • Display Driver Uninstaller完整使用指南:彻底解决显卡驱动问题的终极方案 [特殊字符]
  • 5分钟解锁联想拯救者BIOS隐藏选项:终极免费工具完全指南
  • 使用PyInstaller打包yz-女生-角色扮演-造相Z-Turbo模型为可执行文件
  • 小程序毕业设计基于微信小程序的桃李园速修系统
  • ENSP实战:从零构建企业级WLAN网络
  • 从键盘到单片机:编码器(如74LS147)在嵌入式系统里到底怎么用?一个实例讲透
  • 从CAJ到PDF:解密学术文献格式转换的魔法工具
  • OpenClaw模型量化实践:nanobot镜像8bit压缩Qwen3-4B效果对比
  • Snippet Box:重新定义你的个人代码知识库管理体验
  • 2026年物流托盘工厂揭秘:智能生产如何重塑供应链新格局
  • Android动态分区空间管理实战:从源码配置到终端查询
  • Reachy Mini:开源桌面机器人的完整指南与核心技术解析
  • Learn Claude Code Agent 开发 | 2、插拔式工具系统:扩展功能不修改核心循环
  • 小产后吃什么恢复快?科学修护助力身体回归健康
  • 小程序毕业设计基于微信小程序的生日福利管理系统
  • Windows Cleaner:终极免费解决方案,5分钟彻底解决C盘爆红问题
  • 搜维尔科技:捕捉·训练·扩展·Xsens人形机器人解决方案
  • 高效掌握Mermaid零代码图表工具实战指南:3大核心场景+5个进阶技巧
  • LeaguePrank:英雄联盟个性化展示的安全合规解决方案
  • Qwen2.5-1.5B本地化AI助手效果:实时纠错‘我昨天去北京了’→‘我昨天去了北京’语法修正