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

数据结构之栈

系列文章目录

数据结构之ArrayList-CSDN博客

数据结构之LinkedList-CSDN博客


目录

系列文章目录

前言

一、栈的常用方法

二、栈的模拟实现

三、栈的应用场景

1. 将递归转化为循环,例如链表的逆序打印:

 2. 括号匹配

3. 逆波兰表达式

 4. 判断栈的序列

 5. 模拟实现最小栈

 四、虚拟机栈,栈,栈帧的区别


前言

本文介绍了栈的常用方法,栈的模拟实现以及栈的典型应用场景。


一、栈的常用方法

栈是一种特殊的线性表,只允许在固定的一端进行插入和删除操作。先进栈的元素后出栈,后进栈的元素先出栈。常用方法如下:

Stack(): 构造方法;

push(E): E 在栈顶新增一个元素;

pop(): E 取出栈顶元素;

peek(): E 看一下栈顶元素;

empty() 判断栈是否为空;

size(): int 返回栈中元素的个数;

二、栈的模拟实现

栈的底层是一个数组,与顺序表的实现方法类似。

import java.util.Arrays;public class MyStack {private int[] elem;private int usedSize;private static final int DEFAULT_CAPACITY = 10;public MyStack(){this.elem = new int[DEFAULT_CAPACITY];}public void push(int val){if(isFull()){this.elem = Arrays.copyOf(this.elem, this.elem.length * 2);}this.elem[usedSize++] = val;}private boolean isFull(){return this.usedSize == this.elem.length;}public int pop(){if(isEmpty()) {throw new RuntimeException("栈为空");}this.usedSize--;return this.elem[usedSize];}public boolean isEmpty(){return this.usedSize == 0;}public int peek(){return this.elem[usedSize - 1];}public int size(){return this.usedSize;}
}

三、栈的应用场景

1. 将递归转化为循环,例如链表的逆序打印:

递归方式:

    public void reversePrint(ListNode head){if(head != null){reversePrint(head.next);System.out.print(head.val + " ");}}

栈方式:

    public void reversePrintByStack(ListNode head){ListNode cur = head;Stack<ListNode> stack = new Stack<>();while(cur != null){stack.push(cur);cur = cur.next;}while(!stack.isEmpty()){ListNode top = stack.pop();System.out.print(top.val + " ");}System.out.println();}

 2. 括号匹配

给定一个只包括 '('')''{''}''['']' 的字符串 s ,判断字符串是否有效。

有效字符串需满足:

  1. 左括号必须用相同类型的右括号闭合。

  2. 左括号必须以正确的顺序闭合。

  3. 每个右括号都有一个对应的相同类型的左括号。

    public boolean isValid(String s) {char[] sArr = s.toCharArray();Stack<Character> stack = new Stack<>();for(char ch : sArr){if(ch == '(' || ch == '[' || ch == '{'){stack.push(ch);}else{if(stack.isEmpty()) return false;else{char c = stack.pop();if((c == '(' && ch != ')') || (c == '[' && ch != ']') || (c == '{' && ch != '}')) {return false;}}}}return stack.isEmpty();}

3. 逆波兰表达式

以如下表达式为例:

中缀表达式,即符合我们习惯的表达式,例如:a + b * c + (d * e + f) * g

后缀表达式,即逆波兰表达式,计算机实际运算时采用的表达式,是没有括号的;

中缀表达式转后缀表达式的方法:

先按照运算顺序加括号,例如:((a + (b * c)) + (((d * e) + f) * g));

再将运算符移到括号后面,去掉所有括号,例如:a b c * + d e * f + g * +;

计算后缀表达式:遍历后续表达式

遇到数字:加入到栈中;

遇到运算符:以 * 为例,弹出栈顶元素存到 right 中,再弹出栈顶元素存到 left 中,运算  left * right,将计算的结果再存到栈中;

最终栈中存的元素就是表达式的结果;

    public int evalRPN(String[] tokens) {Stack<Integer> stack = new Stack<>();for(String s : tokens){if("+".equals(s) || "-".equals(s) || "*".equals(s) || "/".equals(s)){int right = stack.pop();int left = stack.pop();switch(s){case "+":{stack.push(left + right); break;}case "-":{stack.push(left - right); break;}case "*":{stack.push(left * right); break;}case "/":{stack.push(left / right); break;}}}else{int t = Integer.parseInt(s);stack.push(t);}}return stack.peek();}

 4. 判断栈的序列

描述:输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否可能为该栈的弹出顺序。假设压入栈的所有数字均不相等。例如序列1,2,3,4,5是某栈的压入顺序,序列4,5,3,2,1是该压栈序列对应的一个弹出序列,但4,3,5,1,2就不可能是该压栈序列的弹出序列。

1. 0<=pushV.length == popV.length <=1000

2. -1000<=pushV[i]<=1000

3. pushV 的所有数字均不相同

    public boolean IsPopOrder (int[] pushV, int[] popV) {Stack<Integer> stack = new Stack<>();int n = pushV.length;int j = 0;for(int i = 0; i < n; i++){stack.push(pushV[i]);while(!stack.isEmpty() && popV[j] == stack.peek()){stack.pop();j++;}}return stack.isEmpty();}

 5. 模拟实现最小栈

设计一个支持 push ,pop ,top 操作,并能在常数时间内(O(1)时间复杂度)检索到最小元素的栈。

实现 MinStack 类:

  • MinStack() 初始化堆栈对象。

  • void push(int val) 将元素val推入堆栈。

  • void pop() 删除堆栈顶部的元素。

  • int top() 获取堆栈顶部的元素。

  • int getMin() 获取堆栈中的最小元素。

class MinStack {private Stack<Integer> stack;private Stack<Integer> minStack;public MinStack() {stack = new Stack<>();minStack = new Stack<>();}public void push(int val) {stack.push(val);if(minStack.isEmpty()){minStack.push(val);}else{int top = minStack.peek();if(top >= val){minStack.push(val);}}}public void pop() {int val = 0;if(!stack.isEmpty()){val = stack.pop();if(minStack.peek() == val){minStack.pop();}}}public int top() {if(stack.isEmpty()){return -1;}return stack.peek();}public int getMin() {if(minStack.isEmpty()){return -1;}return minStack.peek();}
}

 四、虚拟机栈,栈,栈帧的区别

栈:指的是数据结构栈;

虚拟机栈:内存上的一块区域,用于存放方法调用的相关信息,包括局部变量,返回地址等;

栈帧:调用方法时,会在栈上开辟一块空间;


http://www.lqws.cn/news/198829.html

相关文章:

  • 《绩效管理》要点总结与分享
  • 大数据(2) 大数据处理架构Hadoop
  • Linux(13)——Ext系列文件系统
  • jenkins gerrit-trigger插件配置
  • Python Copilot【代码辅助工具】 简介
  • 数据库系统概论(十七)超详细讲解数据库规范化与五大范式(从函数依赖到多值依赖,再到五大范式,附带例题,表格,知识图谱对比带你一步步掌握)
  • Docker容器部署elasticsearch8.*与Kibana8.*版本使用filebeat采集日志
  • SAP学习笔记 - 开发26 - 前端Fiori开发 OData V2 和 V4 的差异 (Deepseek整理)
  • 阿里云MaxCompute入门
  • Fetch与Axios:区别、联系、优缺点及使用差异
  • 使用Python和Scikit-Learn实现机器学习模型调优
  • LinkedList、Vector、Set
  • ⚡️ Linux Docker 基本命令参数详解
  • 开源之夏·西安电子科技大学站精彩回顾:OpenTiny开源技术下沉校园,点燃高校开发者技术热情
  • C++2025.6.7 C++五级考题
  • 在Ubuntu上使用 dd 工具制作U盘启动盘
  • 【hadoop】相关集群开启命令
  • STM32的系统滴答定时器简述
  • 在 Win10 上 WSL 安装 Debian 12 后,Linux 如何启动 SMTP 服务?
  • 人工智能--AI换脸
  • 【工作记录】接口功能测试总结
  • 基于vscode,idea,java,html,css,vue,echart,maven,springboot,mysql数据库,在线考试系统
  • LeetCode刷题 -- 542. 【01 矩阵】最短距离更新算法实现(双向DP)
  • Vue学习之---nextTick
  • hmdp知识点
  • 【精选】计算机毕业设计Python Flask海口天气数据分析可视化系统 气象数据采集处理 天气趋势图表展示 数据可视化平台源码+论文+PPT+讲解
  • Supersonic 新一代AI数据分析平台
  • 深入了解UDP套接字:构建高效网络通信
  • YOLO11解决方案之分析
  • day26-计算机网络-4