数据结构之栈的讲解

 💕"

春宵一刻值千金,花有清香月有阴。

"💕

作者:Mylvzi 

 文章主要内容:leetcode刷题之哈希表的应用(1) 

1.栈的概念

  栈是一种只允许在一端(栈顶)进行数据操作的数据结构,具有“后进先出”的特性,也叫做Last in First Out

最常见的现实生活中的例子就是压子弹  只能一端压子弹

2.栈的模拟实现

  我们想想什么可以实现栈的操作呢?我们知道,栈最大的特性就行只能在一端进行数据操作,使用数组可以更好的模拟栈

  数组的末尾就是我的栈顶,操作栈顶就是操作数组的最后一个元素,而数组最后一个元素的添加,删除都很方便!!!

 1.使用数组模拟

public class MyStack {/*** 栈的实现一:用数组实现栈*/private int[] elem;private int usedSize;private static final int DEFAULTCAPACITY = 10;public MyStack() {this.elem = new int[DEFAULTCAPACITY];}public MyStack(int size) {this.elem = new int[size];}public void push(int val) {if (isFull()) {this.elem = Arrays.copyOf(this.elem,2*this.elem.length);}this.elem[usedSize] = val;this.usedSize++;}private boolean isFull() {return this.usedSize == this.elem.length;
/*        if (this.elem.length == this.usedSize) {return true;}return false;*/}public int pop() {if (isEmpty()) {throw new StackEmptyException("栈区之内不含有数据,无法删除");}//        this.usedSize--;
//        return this.elem[usedSize];int oldVal = this.elem[usedSize-1];this.usedSize--;return oldVal;}public int peek() {if (isEmpty()) {throw new StackEmptyException("栈区之内不含有数据,无法删除");}return this.elem[usedSize-1];}public boolean isEmpty() {return this.usedSize == 0;
/*        if (this.usedSize == 0) {return true;}return false;*/}}

2.使用链表模拟

当然除了使用数组模拟栈,使用链表也可以实现栈的功能(Java中的LinkedList本质上是一个无头双向非循环链表)

class Mystack3 {// 使用链表模拟栈/*** 栈只能在一端进行数据的操作* 在这里我们只在链表的last进行数据的操作*/LinkedList<Integer> mystack = new LinkedList<>();// pushpublic void push(int data) {mystack.addLast(data);}// poppublic int pop() {if(mystack.isEmpty()) {return -1;// 抛异常也可以}return mystack.pollLast();}public int peek() {return mystack.peekLast();}public static void main(String[] args) {Mystack3 mystack3 = new Mystack3();mystack3.push(1);mystack3.push(2);mystack3.push(3);System.out.println(mystack3.pop());// 3System.out.println(mystack3.peek());// 2}
}

3.Java中的栈Stack

  Java中提供了现成的栈供我们使用

代码演示 

// 栈的创建  栈在Java中就是一个类!!!Stack<Integer> stack = new Stack<>();stack.push(1);stack.push(2);stack.push(3);stack.push(4);// 使用构造器Iterator<Integer> it= stack.iterator();while (it.hasNext()) {System.out.print(it.next()+" ");// 1 2 3 4}System.out.println();System.out.println("============================");// 重写了toString方法  直接传对象 即可打印内容System.out.println(stack);// 1 2 3 4// pop会删除栈顶元素stack.pop();System.out.println(stack);// 1 2 3// peek  瞄一眼  不会把top删除int x = stack.peek();System.out.println(x);// 3}

 4.栈的应用场景

1.括号匹配问题

20. 有效的括号 - 力扣(LeetCode)icon-default.png?t=N7T8https://leetcode.cn/problems/valid-parentheses/

分析:

代码实现:

class Solution {public static boolean isValid(String s) {if(s.length() % 2 != 0) return false;Stack<Character> stack = new Stack<>();for (int i = 0; i < s.length(); i++) {// 获取当前字符char ch = s.charAt(i);// 左括号if(ch == '(' || ch == '{' || ch == '[') {stack.push(ch);}else {// 右括号if(stack.isEmpty()) {return false;}else {// 要进行括号匹配char top = stack.peek();if(ch == '}' && top == '{' || ch == ')' && top == '(' ||ch == ']' && top == '[') {stack.pop();}else {return false;}}}}return stack.isEmpty();}
}

也可以使用顺序表实现

class Solution {public static boolean isValid(String s) {if(s.length() % 2 != 0) return false;List<Character> list = new ArrayList<>();for (int i = 0; i < s.length(); i++) {// 获取当前字符char ch = s.charAt(i);// 左括号if(ch == '(' || ch == '{' || ch == '[') {list.add(ch);}else {// 右括号if(list.isEmpty()) {return false;}else {// 要进行括号匹配char top = list.get(list.size()-1);if(ch == '}' && top == '{' || ch == ')' && top == '(' ||ch == ']' && top == '[') {list.remove(list.size()-1);}else {return false;}}}}return list.isEmpty();}}

2.后缀表达式

 代码实现:

class Solution {public int evalRPN(String[] tokens) {// 遇到数字存放到栈中Stack<Integer> stack = new Stack<>();// 循环遍历所给字符串for(String s : tokens) {// 数字if(!isOperation(s)) {// 是数字就pushstack.push(Integer.parseInt(s));}else {// 运算符// 先弹出的作右运算符  后弹出的是左运算符int num2 = stack.pop();int num1 = stack.pop();switch(s) {case "+":stack.push(num1+num2);break;case "-":stack.push(num1-num2);break;case "*":stack.push(num1*num2);break;case "/":stack.push(num1/num2);break;    }}}// 遍历完  返回栈的最后一个(唯一一个)元素return stack.pop();}// 判断是否是运算符private boolean isOperation(String s) {if(s.equals("+") || s.equals("-") || s.equals("*") || s.equals("/")) {return true;}return false;}
}

 3.最小栈

力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台icon-default.png?t=N7T8https://leetcode.cn/problems/min-stack/submissions/分析思路:

代码实现:使用两个栈

    class MinStack {//思路1 使用两个栈private Stack<Integer> stack;private Stack<Integer> minstack;// 存放过程中的最小值public MinStack() {this.stack = new Stack<>();this.minstack = new Stack<>();}public void push(int val) {if(minstack.isEmpty()) {minstack.push(val);}else {if (val <= minstack.peek()) {minstack.push(val);}}stack.push(val);}public void pop() {if(!stack.isEmpty()) {int top = stack.pop();if (top == minstack.peek()) {minstack.pop();}}}public int top() {if(stack.empty()) {return -1;}return stack.peek();}public int getMin() {if (minstack.isEmpty()) {return -1;}return minstack.peek();}}

 思路2:使用链表实现

画图分析

代码实现

 class MinStack {// 使用链表实现private class Node{int val;int min;Node next = null;public Node(int val, int min) {this.val = val;this.min = min;}}private Node head;public void push(int x) {if(head == null) {head = new Node(x,x);}else {Node newNode = new Node(x,Math.min(x,head.min));newNode.next = head;head = newNode;}}public void pop() {head = head.next;}public int top() {return head.val;}public int getMin() {return head.min;}}

4.用栈实现队列

232. 用栈实现队列 - 力扣(LeetCode)

class MyQueue {// 只需要转移一次就能实现顺序的完全颠倒private Stack<Integer> stack1;private Stack<Integer> stack2;public MyQueue() {stack1 = new Stack<>();stack2 = new Stack<>();}public void push(int x) {// stack1的栈底元素才是我第一个要出的元素stack1.push(x);}public int pop() {// 只有当s2为空的时候才需要从s1中转移数据,否则就一直出s2中的数据即可if(stack2.empty()) {while(!stack1.empty()) {stack2.push(stack1.pop());}}return stack2.pop();}public int peek() {if (stack2.empty()) {while(!stack1.empty()) {stack2.push(stack1.pop());}}return stack2.peek();}public boolean empty() {return stack2.empty() && stack1.empty();}
}

5.栈的压入、弹出序列

栈的压入、弹出序列_牛客题霸_牛客网 (nowcoder.com)

使用一个辅助站来模拟栈的入栈和出栈

代码实现

import java.util.*;public class Solution {/*** 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可** * @param pushV int整型一维数组 * @param popV int整型一维数组 * @return bool布尔型*/public boolean IsPopOrder (int[] pushV, int[] popV) {// write code here// 使用辅助栈 模拟出栈的过程Stack<Integer> stack = new Stack<>();// j去遍历入栈数组int j = 0;for (int i = 0; i < pushV.length; i++) {// 当j没有遍历完  &&(栈为空 || 栈顶和出栈的数组的元素不同)--入栈while(j< pushV.length &&(stack.isEmpty() || stack.peek()!=popV[i])) {stack.push(pushV[j++]);}// 出循环  栈顶和popV[i]相等if(stack.peek() == popV[i]) {stack.pop();}else {return false;}}return true;}
}

思路2:开辟辅助栈  遍历入栈序列  相等就出栈  最后判断栈是否为空

    public boolean IsPopOrder (int[] pushV, int[] popV) {// write code here// 使用辅助栈 模拟出栈的过程Stack<Integer> stack = new Stack<>();int j = 0;// 遍历出栈序列for (int i = 0; i < pushV.length; i++) {stack.push(pushV[i]);while (!stack.isEmpty() && stack.peek() == popV[j]) {stack.pop();j++;}}return stack.isEmpty();}

思路3:使用size来抽象代替栈的元素个数

  把入栈序列遍历完,最后看是否为空

    public boolean IsPopOrder (int[] pushV, int[] popV) {// write code hereint size = 0,j=0;for (int num:pushV) {pushV[size] = num;// 出栈序列和栈顶元素相等  模拟出栈while(size >=0 && popV[j] == pushV[size]) {size--;j++;}size++;}return size == 0;}

使用下标+数组可以模拟栈的操作,使空间复杂度为0(1)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/157030.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

如何把A3 pdf 文章打印成A4

1. 用Adobe Acrobat 打开pdf 2 打印 选择海报 进行调整即可如下图,见下面红色的部分。

说一下类的生命周期

&#x1f47d;System.out.println(“&#x1f44b;&#x1f3fc;嗨&#xff0c;大家好&#xff0c;我是代码不会敲的小符&#xff0c;双非大四&#xff0c;Java实习中…”); &#x1f4da;System.out.println(“&#x1f388;如果文章中有错误的地方&#xff0c;恳请大家指正&a…

MySQL MHA高可用配置及故障切换

一、MHA相关概念 1&#xff0e;什么是 MHA MHA&#xff08;MasterHigh Availability&#xff09;是一套优秀的MySQL高可用环境下故障切换和主从复制的软件。 MHA 的出现就是解决MySQL 单点的问题。 MySQL故障切换过程中&#xff0c;MHA能做到0-30秒内自动完成故障切换操作。 …

二百零七、Flume——Flume实时采集5分钟频率的Kafka数据直接写入ODS层表的HDFS文件路径下

一、目的 在离线数仓中&#xff0c;需要用Flume去采集Kafka中的数据&#xff0c;然后写入HDFS中。 由于每种数据类型的频率、数据大小、数据规模不同&#xff0c;因此每种数据的采集需要不同的Flume配置文件。玩了几天Flume&#xff0c;感觉Flume的使用难点就是配置文件 二、…

信号的处理时机(内核态,用户态,如何/为什么相互转换,内核空间,cpu寄存器),信号的处理流程详细介绍+抽象图解

目录 信号的处理时机 引入 思考 -- 什么时候才能算合适的时候呢? 用户态转为内核态 引入 内核地址空间 引入 思考 -- 进程为什么能切换成内核态呢? 虚拟地址空间 注意点 原理 (总结一下) 为什么如何进入内核态 引入 介绍 底层原理(int 80) cpu的寄存器 用…

nodejs express vue uniapp新闻发布系统源码

开发技术&#xff1a; node.js&#xff0c;mysql5.7&#xff0c;vscode&#xff0c;HBuilder nodejs express vue uniapp 功能介绍&#xff1a; 用户端&#xff1a; 登录注册 首页显示搜索新闻&#xff0c;新闻分类&#xff0c;新闻列表 点击新闻进入新闻详情&#xff0…

计算机网络——网络可靠性及网络出口配置

1. 前言&#xff1a; 学习目标&#xff1a; 1.了解链路聚合的作用 2. 了解ACL的工作原理 3. 了解NAT的工作原理和配置 2. 网络可靠性方案 网络可靠性是指网络在面对各种异常情况或故障时&#xff0c;能够维持正常运行和提供服务的能力。这包括防止网络中断、减小数据丢失的可能…

spring boot零配置

spring boot是如何选择tomcat还是Jett作为底层服务器的呢&#xff1f; springboot通过ServletWebServerApplicationContext的onRefresh()方法&#xff0c;会创建web服务 protected void onRefresh() {super.onRefresh();try {// 创建web服务createWebServer();}catch (Throwab…

PyTorch 之 Dataset 类入门学习

PyTorch 之 Dataset 类入门学习 Dataset 类简介 PyTorch 中的 Dataset 类是一个抽象类&#xff0c;用来表示数据集。通过继承 Dataset 类可以进行自定义数据集的格式、大小和其它属性&#xff0c;供后续使用&#xff1b; 可以看到官方封装好的数据集也是直接或间接的继承自 …

6.Gin 路由详解 - GET POST 请求以及参数获取示例

6.Gin 路由详解 - GET POST 请求以及参数获取示例 GET POST 请求以及参数获取示例 Get 请求&#xff1a;获取 Quary 参数 // 获取query参数示例&#xff1a;GET /user?uid20&namejack&page1 r.GET("/user", func(c *gin.Context) {// 获取参数// Query获取参…

[机缘参悟-119] :一个IT人的反思:反者道之动;弱者,道之用 VS 恒者恒强,弱者恒弱的马太效应

目录 前言&#xff1a; 一、道家的核心思想 二、恒者恒强&#xff0c;弱者恒弱的马太效应 三、马太效应与道家思想的统一 3.1 大多数的理解 3.2 个人的理解 四、矛盾的对立统一 前言&#xff1a; 马太效应和强弱互转的道家思想&#xff0c;都反应了自然规律和社会规律&…

SVN 修改版本库地址url路径

一、win11用户 1. win11系统右链菜单比较优秀&#xff0c;如果菜单中选择“TortoiseSVN”找不到“重新定位”&#xff0c;如下图所示&#xff0c;则需要添加右键菜单&#xff1a; 2.添加右键菜单&#xff1a;选择“TortoiseSVN”&#xff0c;点击设置&#xff0c;如下图所示&a…

Vue 项目实战——如何在页面中展示 PDF 文件以及 PDFObject 插件实战

文章目录 &#x1f4cb;前言&#x1f3af;使用 HTML 标签&#x1f9e9; embed 标签&#x1f9e9; object标签&#x1f9e9; iframe标签&#x1f9e9;完整代码 &#x1f3af;使用 PDFObject 插件&#x1f9e9;为什么使用 PDFObject 插件&#xff08;AI翻译&#xff09;&#x1f…

【微服务】SaaS云智慧工地管理平台源码

智慧工地系统是一种利用人工智能和物联网技术来监测和管理建筑工地的系统。它可以通过感知设备、数据处理和分析、智能控制等技术手段&#xff0c;实现对工地施工、设备状态、人员安全等方面的实时监控和管理。 一、智慧工地让工程施工智能化 1、内容全面&#xff0c;多维度数…

华为云IoT与OpenHarmony深度协同,加速设备上鸿即上云【云驻共创】

本次专题论坛探讨了华为云IoT与Open Harmony的深度协同、边缘屏蔽硬件差异、实现智慧隧道全方位智能化管理&#xff0c;以及华为云与Open Harmony生态的合作。同时也介绍了华为云物联网卡平台、HTTP2协议以及华为物联网在交通领域的应用。 一&#xff0e;华为云IoT与Open Harm…

数学几百年重大错误:将两异函数误为同一函数

黄小宁 因各实数都可是数轴上点的坐标所以数集A可形象化为数轴上的点集A&#xff0c;从而使x∈R变换为实数yxδ的几何意义可是&#xff1a;一维空间“管道”g内R轴上的质点x∈R(x是点的坐标)运动到新的位置yxδ还在管道g内&#xff08;设各点只作位置改变而没别的改变即变位前…

Vue学习

1。 搭框架 依赖等 创建vue项目 vue create 项目名称 vue create [options] <app-name>使用vite npm init vitelatest <app-name>-- --template vue 目录调整1 apiutilsvenderimages、styles 配置文件 jsconfig.json 配置之后路径可以直接使用 / {"comp…

mysql 查询

-- 多表查询select * from tb_dept,tb_emp; 内来链接 -- 内连接 -- A 查询员工的姓名 &#xff0c; 及所属的部门名称 &#xff08;隐式内连接实现&#xff09;select tb_emp.name,tb_dept.name from tb_emp,tb_dept where tb_emp.idtb_emp.id;-- 推荐使用select a.name,b.n…

【精选】OpenCV多视角摄像头融合的目标检测系统:全面部署指南&源代码

1.研究背景与意义 随着计算机视觉和图像处理技术的快速发展&#xff0c;人们对于多摄像头拼接行人检测系统的需求日益增加。这种系统可以利用多个摄像头的视角&#xff0c;实时监测和跟踪行人的活动&#xff0c;为公共安全、交通管理、视频监控等领域提供重要的支持和帮助。 …

TS类型全解

使用TypeScript开发的程序更安全&#xff0c;常见的错误都能检查出来。TS能让程序员事半功倍。而原因在于TS的“类型安全”&#xff08;借助类型避免程序做无效的事情&#xff09;。 图 运行程序的过程 但是TS不会直接编译成字节码&#xff0c;而是编译成JavaScript代码。TS编…