【Java数据结构】详解Stack与Queue(二)

🔒文章目录:

1.❤️❤️前言~🥳🎉🎉🎉

2.栈的应用场景 

2.1逆序打印链表

2.2逆波兰表达式求值

2.3括号匹配

2.4出栈入栈次序匹配

2.5最小栈 

3. 栈 虚拟机栈 栈帧的区别

4.总结 


1.❤️❤️前言~🥳🎉🎉🎉

Hello, Hello~ 亲爱的朋友们👋👋,这里是E绵绵呀✍️✍️。

如果你喜欢这篇文章,请别吝啬你的点赞❤️❤️和收藏📖📖。如果你对我的内容感兴趣,记得关注我👀👀以便不错过每一篇精彩。

当然,如果在阅读中发现任何问题或疑问,我非常欢迎你在评论区留言指正🗨️🗨️。让我们共同努力,一起进步!

加油,一起CHIN UP!💪💪

🔗个人主页:E绵绵的博客
📚所属专栏:

1. JAVA知识点专栏

        深入探索JAVA的核心概念与技术细节

2.JAVA题目练习

        实战演练,巩固JAVA编程技能

3.c语言知识点专栏

        揭示c语言的底层逻辑与高级特性

4.c语言题目练习

        挑战自我,提升c语言编程能力

📘 持续更新中,敬请期待❤️❤️ 

文章借鉴于【Java---数据结构】栈(Stack)_stack java-CSDN博客 。

2.栈的应用场景 

2.1逆序打印链表

一般我们可以用递归去逆序打印链表。


// 递归方式
void printList(Node head){
    if(null != head){
        printList(head.next);
        System.out.print(head.val + " ");
   }
}

除此之外我们还可以用另一种特殊方法,就是利用栈去打印,代码展示在这。相比递归其更高效。


// 循环方式
void printList(Node head){
    if(null == head){
        return;
   }
    
    Stack<Node> s = new Stack<>();
    // 将链表中的结点保存在栈中
    Node cur = head;
    while(null != cur){
        s.push(cur);
        cur = cur.next;
   }
    // 将栈中的元素出栈
    while(!s.empty()){
        System.out.print(s.pop().val + " ");
   }
}

 2.2逆波兰表达式求值

题目描述: 

给你一个字符串数组 tokens ,表示一个根据 逆波兰表示法 表示的算术表达式。

请你计算该表达式,返回一个表示表达式值的整数。

  • 注意:两个整数之间的除法只保留整数部分。
  • 可以保证给定的逆波兰表达式总是有效的。换句话说,表达式总会得出有效数值且不存在除数为 0 的情况。

 示例 :

输入:tokens = ["2","1","+","3","*"]
输出:9
解释:该算式转化为常见的中缀算术表达式为:((2 + 1) * 3) = 9

🍓逆波兰表达式:逆波兰表达式是一种后缀表达式,所谓后缀就是指运算符写在后面 

  • 平常使用的算式则是一种中缀表达式,如 ( 1 + 2 ) * ( 3 + 4 ) 。
  • 该算式的逆波兰表达式写法为 1 2 +  3 4 + * 。

✨前、中、后缀表达式的转换:

  • 将中缀表达式按运算顺序加上括号,从左到右分别将运算符移到对应括号的最右边,再去掉所有括号,就能得到后缀表达式。
  • 同理将运算符移到对应括号的最左边就得到了前缀表达式。


🌌逆波兰表达式主要有以下两个优点:

  1. 去掉括号后表达式无歧义,上式即便写成 1 2 + 3 4 + * 也可以依据次序计算出正确结果。
  2. 适合用栈操作运算:遇到数字则入栈;遇到算符则取出栈顶两个数字进行计算,并将结果压入栈中

所以我们可以根据其第二个优点作为思路去求逆波兰表达式的值

⏳解题思路: 

1.创建一个存放整型数据的栈。遍历字符串数组,遇到数字就入栈。遇到运算符则取出栈顶的两个元素进行计算,再将计算后的结果入栈。
2.写一个方法isOperation(),判断字符串数组中的字符是不是运算符。
3.遍历字符串数组,调用isOperation()方法。如果当前字符不是运算符,则将字符转换为对应的十进制整数并入栈。如果当前字符是运算符则取出两个元素进行计算(出栈)。再计算后的结果入栈。


需要注意:先出栈的元素放到运算符的右边,后出栈的元素放到运算符的左边。
最终栈顶元素的值为计算的结果,返回栈顶元素即可。


完整代码及测试 :

public class Test1 {
    public static void main(String[] args) {
        String[]  a={"1","2","+","3","4","*","+"};
        Solution solution=new Solution();
        System.out.println( solution.evalRPN(a));
    }
    }

class Solution {
    public int evalRPN(String[] tokens) {
        Stack<Integer> stack=new Stack();
        int a=0;
        for(;a<tokens.length;a++){
            if(checkDo(tokens[a])==true){
                switch(tokens[a]){
                    case "+":
                        stack.push(stack.pop()+stack.pop());
                        break;
                    case "-":
                       int b=stack.pop();
                       int c=stack.pop();
                       stack.push(c-b);
                        break;
                    case "*":
                        stack.push(stack.pop()*stack.pop());
                    break;
                     case "/":
                        int g=stack.pop();
                        int f=stack.pop();
                        stack.push(f/g);
                        break;
                }}
            else{
                stack.push(Integer.parseInt(tokens[a]));
            }
        }
        return stack.pop();
    }
    public Boolean checkDo(String a){
        if(a.equals("+")||a.equals("-")||a.equals("/")||a.equals("*")){
            return true;
        }
        return  false;
    }
}

该题链接:逆波兰表达式求值 

 2.3括号匹配

📌题目描述: 

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

有效字符串需满足:

  • 左括号必须用相同类型的右括号闭合。
  • 左括号必须以正确的顺序闭合。

📋题目示例:

示例1:
输入:s = "()[]{}"
输出:true
 
示例2:
输入:s = "([)]"
输出:false 

⏳解题思路:

1.创建一个存放字符数据的栈。遍历字符串,使用charAt()方法获取字符串中的每一个字符。
如果字符是左括号就进行入栈操作(左括号:'(' , '[' , '{' )。
1.分析括号不匹配的情况有三种:

左括号多:(((((   )))
右括号多:(((    )))))
左右括号次序不匹配:(  [   )  ]
2.不匹配:

因为栈当中存储的是左括号,如果当 i 遍历完整个字符串,栈还是不为空,那么就是左括号多。返回false。
如果当前字符是右括号,且栈为空,那么就是右括号多,返回false。
如果当前字符是右括号,栈顶元素与当前的右括号字符不匹配,返回false。
3.匹配:(  [  ]  )

如果字符是右括号,判断栈顶元素与当前的右括号字符是否匹配,如果匹配就进行出栈操作,直到遍历完整个字符串,且我们的栈为空则返回true。

完整代码及测试如下: 

import java.util.*;
public class Test2 {
    public boolean isValid(String s) {
        Stack<Character> stack=new Stack<>();
        for(int a=0;a<s.length();a++){
            char i=s.charAt(a);
            if(i=='{'||i=='('||i=='[')
                stack.push(i);
            else{
                if(stack.empty()==true)
                    return false;
                if((stack.peek()=='('&&i==')')||(stack.peek()=='{'&&i=='}')||(stack.peek()=='['&&i==']'))
                    stack.pop();
                else
                    return  false;
            }
        }
        if(stack.empty()!=true)
            return false;
        else
            return true;
    }

    public static void main(String[] args) {
         Test2 test2=new Test2();
        System.out.println(test2.isValid("{{{}}}([])"));
    }

}

该题链接:括号匹配 

2.4出栈入栈次序匹配

📌题目描述:

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

0<=pushV.length == popV.length <=1000
 -1000<=pushV[i]<=1000
pushV 的所有数字均不相同

📋题目示例:

输入:[1,2,3,4,5],[4,5,3,2,1]
 
返回值:true
说明:
可以通过 push(1)=>push(2)=>push(3)=>push(4)=>pop()=>push(5)=>pop()=>pop()=>pop()=>pop()
这样的顺序得到[4,5,3,2,1]这个序列,返回true       

⏳解题思路:

  1. 首先,遍历第一个序列,将第一个序列的第一个元素压入栈中;
  2. 遍历第二个序列,每次判断当前栈顶元素是否与第二个序列的当前元素相同;
  3. 如果相同,则弹出栈顶元素,并且将第二个序列的指针向后移动一位;而后重复第二个步骤的判断。
  4. 如果不同,则继续将第一个序列的元素压入栈中,直到找到一个与第二个序列当前元素相同的栈顶元素为止,或者直至循环结束;
  5. 最后,如果栈为空,则说明第二个序列是第一个序列的一个合法的弹出顺序,返回true;否则,返回false

 完整代码及测试如下:

public class Test4 {
    public static void main(String[] args) {
        int[] pushV={1,2,3,4,5};
        int[] popV={4,5,3,2,1};
         Main main=new Main();
        System.out.println(main.IsPopOrder(pushV, popV));
    }


}
 class Main {
    public boolean IsPopOrder (int[] pushV, int[] popV) {

        Stack<Integer> stack=new Stack<>();
        int j=0;
        for(int i=0;i<pushV.length;i++){
            stack.push(pushV[i]);
            while(!stack.empty()&&popV[j]==stack.peek()){
                j++;
                stack.pop();
            }
        }
        if(stack.empty())
            return true;
        else
            return false;
    }
}

该题链接:出栈入栈次序匹配 

2.5最小栈 

📌题目描述

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

实现 MinStack 类:

MinStack() 初始化堆栈对象。
void push(int val) 将元素val推入堆栈。
void pop() 删除堆栈顶部的元素。
int top() 获取堆栈顶部的元素。
int getMin() 获取堆栈中的最小元素。

 📋题目示例:

输入:
["MinStack","push","push","push","getMin","pop","top","getMin"]
[[],[-2],[0],[-3],[],[],[],[]]
 
输出:[null,null,null,null,-3,null,0,-2]
 
解释:
MinStack minStack = new MinStack();
minStack.push(-2);
minStack.push(0);
minStack.push(-3);
minStack.getMin();   --> 返回 -3.
minStack.pop();
minStack.top();      --> 返回 0.
minStack.getMin();   --> 返回 -2.

⏳解题思路:

创建两个栈,一个普通栈,一个最小栈。

入栈:

所有元素都要放入普通栈,判断元素是否放入最小栈,如果最小值为空,则直接将元素入最小栈。如果最小栈中有元素,将待入栈元素与最小栈的栈顶元素进行比较,如果待入栈元素小于或等于最小栈中的栈顶元素,则将元素也放入最小栈,否则就不放入最小栈。
出栈:

普通栈中的元素都要进行出栈操作。如果最小栈的栈顶元素等于普通栈的栈顶元素,那么最小栈也进行出栈操作,否则最小栈中的元素不出栈。
返回值:

top()方法返回普通栈中的栈顶元素
getMin()方法返回最小栈的栈顶元素

 完整代码及测试如下:

public class Test3 {
    public static void main(String[] args) {
 MinStack minStack=new MinStack();
 minStack.push(512);
 minStack.push(-1024);
 minStack.push(-1024);
 minStack.push(512);
 minStack.pop();
 minStack.pop();
 minStack.pop();
        System.out.println(minStack.getMin());

    }
    }
class MinStack {
    Stack<Integer> stack=new Stack<>();
    Stack<Integer> minStack=new Stack<>();
    public MinStack() {
       ;
    }
    public void push(int val) {
        stack.push(val);
        if(minStack.empty())
            minStack.push(val);
        else{
            if(val<=minStack.peek())
                minStack.push(val);
        }
    }

    public void pop() {
        if(stack.pop().equals(minStack.peek()))
            minStack.pop();
    }


    public int top() {
        return  stack.peek();
    }

    public int getMin() {
        return minStack.peek();
    }
}

该题链接:最小栈 

3. 栈 虚拟机栈 栈帧的区别

栈是一种特殊的数据结构,它具有“先进后出”的特点,栈可以通过入栈(push)和出栈(pop)操作进行数据的存储和读取。

虚拟机栈是Java虚拟机所使用的栈结构,用于存储方法执行时的数据和指令等信息。在Java程序运行时,每个线程都会有一个对应的虚拟机栈。

栈帧是虚拟机栈中的一个元素,它用于存储一个方法的执行状态。在一个方法被执行时,虚拟机就会创建一个对应的栈帧,并将其压入虚拟机栈中。当这个方法执行完毕后,对应的栈帧也会从虚拟机栈中弹出,恢复到调用该方法的上一个方法的执行状态。


因此,栈和虚拟机栈都是数据结构,用于存储数据和指令等信息,但是前者通常是指物理内存中的一块区域,而后者则是Java虚拟机的一种抽象结构。而栈帧则是虚拟机栈中的一个元素,用于存储一个方法的执行状态。

4.总结 

所以对于栈的这些习题我们就讲完了,下篇文章将会给大家讲解队列。在此,我们诚挚地邀请各位大佬们为我们点赞、关注,并在评论区留下您宝贵的意见与建议。让我们共同学习,共同进步,为知识的海洋增添更多宝贵的财富!🎉🎉🎉❤️❤️💕💕🥳👏👏👏

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

1371. 每个元音包含偶数次的最长子字符串

1371. 每个元音包含偶数次的最长子字符串 原题链接&#xff1a;完成情况&#xff1a;解题思路&#xff1a;参考代码&#xff1a;_1371每个元音包含偶数次的最长子字符串 错误经验吸取 原题链接&#xff1a; 1371. 每个元音包含偶数次的最长子字符串 https://leetcode.cn/pro…

Qos基础

一、Qos概述 Qos是一个框架&#xff0c;解决服务质量&#xff0c;尽力而为模型&#xff0c;集成服务以及区分服务模型&#xff0c;流量分类与标识。 使用Qos是带宽不够。 每个接口有硬件队列和软件队列&#xff08;队列排满了就不会再排&#xff09;。 企业宽带一般都是上行和下…

使用 Scapy 库编写 ICMP 重定向攻击脚本

一、介绍 ICMP重定向攻击&#xff08;ICMP Redirect Attack&#xff09;是一种网络攻击&#xff0c;攻击者通过发送伪造的ICMP重定向消息&#xff0c;诱使目标主机更新其路由表&#xff0c;以便将数据包发送到攻击者控制的路由器或其他不可信任的设备上。该攻击利用了ICMP协议…

【三维重建NeRF(三)】Mip-NeRF论文解读

本文结合深蓝学院课程学习和本人的理解&#xff0c;欢迎交流指正 文章目录 Mip-NeRF流程简述混叠问题与MipMapMip-NeRF提出的解决办法圆锥台近似计算与集成位置编码(IPE) Mip-NeRF流程简述 Mip-NeRF的大体流程和NeRF基本是一样的&#xff0c;NeRF介绍 创新的部分就是针对NeRF…

定格动态:如何用前端实现视频帧截图

在这样一个图像化极其重要的时代&#xff0c;从视频中提取精彩瞬间&#xff0c;即视频帧截图的技术&#xff0c;已成为前端开发中的一个亮点。JavaScript作为网页动态效果和交互的主力军&#xff0c;其在视频处理领域能力逐渐被挖掘和重视&#xff0c;尤其是视频帧截图技术的应…

GaN功率电子器件中体缺陷相关机制的建模仿真研究

在电力电子器件的外延生长和器件制备过程中&#xff0c;缺陷是不可避免的&#xff0c;大量的缺陷在一定程度上会牺牲器件的击穿电压、导通电阻等性能&#xff0c;同时影响器件的可靠性。近期&#xff0c;河北工业大学和广东工业大学联合开发了缺陷相关的仿真模型&#xff0c;深…

gitblit 环境搭建,服务器迁移记录

下载 Gitblit&#xff1a; http://www.gitblit.com/ JDK&#xff1a;gitblit网站显示需要jdk1.7&#xff0c;这里用的1.8。 Git&#xff1a;到官网下载最新版本安装 1). 分别安装JDK&#xff0c;Git&#xff0c;配置环境变量&#xff0c;下载并解压Gitblit 2). 创建代码仓库 …

每日一题《leetcode--LCR 029.循环有序列表的插入》

https://leetcode.cn/problems/4ueAj6/ 这道题整体上想插入数据有三种情况&#xff1a; 1、整个列表是空列表&#xff0c;需要返回插入的结点 2、整个列表只有一个结点&#xff0c;需要在头结点后插入新结点&#xff0c;随机把新结点的next指向头结点 3、整个列表的结点 >1 …

052、Python 集合及其使用

集合&#xff08;Set&#xff09;是一种无序且元素唯一的数据结构&#xff0c;用于存储不重复的元素&#xff08;即集合具有无序性和互异性两个重要特性&#xff09;。集合可以用于执行集合操作&#xff0c;如并集、交集、差集等。 定义集合 可以使用大括号 {} 或者 set() 函…

供应MT7662TUN/C进口芯片现货

长期供应各品牌进口芯片现货&#xff1a; MT7662TUN/C DLPC4421A DLPC4422A DAD2000 IT6634 DDP4421-HV PMD1000 SiHA120N60E AM8280 AM90N06-03B P15F60HP2 MSD6A838UYGN-8-003D 5AGXBA5D4F31C5G MCZ5209SN STM32L431CCT6 PT2833 ES858 TPS74301RGWR CSD18…

Rust自动生成文件解析

目录 一、生成目录解析二、生成文件解析2.1 Cargo.toml2.2 main函数解析 一、生成目录解析 先使用cargo clean命令删除所有生成的文件&#xff0c;下图显示了目录结构和 main.rs文件 使用cargo new testrust时自动创建出名为testrust的Rust项目。内部主要包含一个src的源码文…

IP地址SSL证书申请流程与注意事项

申请IP地址SSL证书的过程相对直接&#xff0c;但涉及几个关键步骤和注意事项。以下是基于现有信息整理的申请流程及注意事项概览&#xff1a; 一、IP地址SSL证书申请流程&#xff1a; PC点此申请&#xff1a;IP SSL证书申请-极速签发 注册填写注册码230918&#xff08;填写注…

DeepFace ——用于高级人脸识别算法探索与应用

1. 概述 人脸识别作为人工智能和机器学习中的一个活跃领域&#xff0c;长期以来一直在追求模仿甚至超越人类视觉系统的能力。这项技术在安全、监控、身份验证等多个方面都有着广泛的应用&#xff0c;但同时也伴随着隐私、伦理和准确性等社会和文化方面的考量。 Meta&#xff0…

fly-barrage 前端弹幕库(6):实现人像免遮挡

项目官网地址&#xff1a;https://fly-barrage.netlify.app/&#xff1b; &#x1f451;&#x1f40b;&#x1f389;如果感觉项目还不错的话&#xff0c;还请点下 star &#x1f31f;&#x1f31f;&#x1f31f;。 Gitee&#xff1a;https://gitee.com/fei_fei27/fly-barrage&a…

【matlab】绘图插入并放大/缩小子图

参考链接 代码分为两个&#xff1a;绘图代码与magnify.m 绘图代码就是普通的绘图代码&#xff0c;以下为例 %https://zhuanlan.zhihu.com/p/655767542 clc clear close all x 0:pi/100:2*pi; y1 sin(x); plot(x,y1,r-o); hold on y2sin(x)-0.05; y3sin(x)0.05; xlim([0 2*…

ai写真软件有哪些?轻松创造艺术写真照

艺术写真照是艺术与日常之间的桥梁&#xff0c;它将艺术的边界延伸到了我们的日常生活中&#xff0c;让每个人都能够通过AI技术&#xff0c;将平凡的瞬间转化为艺术的永恒。 那AI写真怎么样呢&#xff1f;今天&#xff0c;本文将推荐几款AI写真软件&#xff0c;它们将帮助你轻…

CXL (1)

为什么有CXL CXL说到底 是为了打破内存墙而生的 CXL全称是Compute Express Link&#xff0c; 可以用来连接CPU&#xff0c;以及其他任何计算单元&#xff0c;比如GPU。 CXL和PCIe跑在一样的physical layer上&#xff0c;与PCIe不一样的是&#xff0c;CXL允许CPU和连接的设备共…

csrf漏洞与ssrf漏洞

环境&#xff1a;用kali搭建的pikachu靶场 一.CSRF 1.CSRF漏洞简介 跨站请求伪造&#xff08;CSRF&#xff09;漏洞是一种Web应用程序安全漏洞&#xff0c;攻击者通过伪装成受信任用户的请求来执行未经授权的操作。这可能导致用户在不知情的情况下执行某些敏感操作&#xff0…

21、matlab生成脉冲序列:pulstran()函数

1、pulstran()函数 1&#xff09;语法 语法1&#xff1a;y pulstran(t,d,func,fs) 基于连续函数的采样产生脉冲序列。 语法2&#xff1a;y pulstran(t,d,p) 生成一个脉冲序列&#xff0c;该脉冲序列是向量p中原型脉冲的多个延迟插值的总和。 语法3&#xff1a;y pulstran…

echarts柱状图坐标轴的内容太长导致显示不全的两种解决办法

情况一&#xff1a;坐标上的内容是文字时 width: 60,//将内容的宽度固定 overflow: truncate,//超出的部分截断 truncate: ...,//截断的部分用...代替 情况二&#xff1a;如果纵坐标上是数字 grid: {top: "15%",left: "2%",right: "2%",bottom:…