Collection与数据结构 Stack与Queue(一): 栈与Stack

news2025/1/18 1:53:21

1. 栈

1.1 概念

栈:一种特殊的线性表,其只允许在固定的一端进行插入和删除元素操作。进行数据插入和删除操作的一端称为栈顶,另一端称为栈底。栈中的数据元素遵守后进先出LIFO(Last In First Out)的原则。
压栈:栈的插入操作叫做进栈/压栈/入栈,入数据在栈顶
出栈:栈的删除操作叫做出栈。出数据在栈顶
在这里插入图片描述
栈在现实生活中的例子:
弹夹:
在这里插入图片描述
羽毛球筒:
在这里插入图片描述

1.2 栈的使用

方法功能
Stack()构造一个空的栈
E push(E e)将e入栈,并返回e
E pop()将栈顶元素出栈并返回
E peek()获取栈顶元素
int size()获取栈中有效元素个数
boolean empty()检测栈是否为空
import java.util.Stack;

public class Main {
    public static void main(String[] args) {
        //使用Stack中自带的方法
        Stack<Integer> stack = new Stack<>();
        stack.push(1);
        stack.push(2);
        stack.push(3);
        stack.push(4);//压栈
        System.out.println(stack.peek());
        System.out.println(stack.peek());//没有弹出元素,只是返回了栈顶元素
        System.out.println(stack.pop());
        System.out.println(stack.pop());//出栈
        System.out.println(stack.size());//计算栈中元素的个数
        System.out.println(stack.empty());//判断栈是否为空
        //使用Stack从Collection继承下来的方法
        Stack<Integer> stack1 = new Stack<>();
        stack1.add(1);
        stack1.add(2);
        stack1.add(3);
        stack1.add(4);//添加元素
        System.out.println(stack1.isEmpty());//判断是否为空
    }
}

运行结果:
在这里插入图片描述

1.3 栈的模拟实现

import java.util.Arrays;

public class MyStack {
    int[] array = new int[5];//默认容积为5
    int size;
    public void push(int x){
        ensureCapacity();
        array[size] = x;
        size++;
    }
    public int pop(){
        int e = peek();
        size--;
        return e;
    }
    public int peek(){
        if (!empty()){
            return array[size-1];
        }
        throw new EmptyExecption("Stack is empty.");
    }
    public boolean empty(){
        if (size == 0){
            return true;
        }
        return false;
    }
    public int size(){
        return this.size;
    }
    private void ensureCapacity(){
        if (this.array.length == size){
            this.array = Arrays.copyOf(array,array.length*2);
        }
    }
}
public class EmptyExecption extends RuntimeException{
    public EmptyExecption(String message) {
        super(message);
    }
}

2. 栈的相关面试题

2.1 括号匹配

OJ链接
在这里插入图片描述

class Solution {
        public boolean isValid(String s) {
            Stack<Character> stack = new Stack<>();
            for (int i = 0; i < s.length(); i++) {
                char c = s.charAt(i);
                if (c == '(' || c == '[' || c == '{') {
                    stack.push(c);//左括号入栈
                }else {
                    if (stack.empty()){
                        return false;//如果在匹配的时候,栈为空,说明右括号赘余
                    }
                    char ch2 = stack.peek();
                    if (ch2 == '(' && c == ')'||ch2 == '[' && c == ']'||ch2 == '{' && c == '}'){
                        stack.pop();
                    }else {
                        return false;//括号不匹配
                    }
                }
            }
            return stack.empty();//遍历完了,栈中还有元素,说明左括号赘余
        }
    }

上述代码逻辑较为复杂,我们通过一张图来理清楚:
在这里插入图片描述

2.2 逆波兰表达式求值

OJ链接
在这里插入图片描述

class Solution2 {
        public int evalRPN(String[] tokens) {
            Stack<Integer> stack = new Stack<>();
            for (int i = 0; i < tokens.length; i++) {
                String s = tokens[i];
                if (isOperation(s)){
                    int x1 = stack.pop();
                    int x2 = stack.pop();//把两个数字出栈
                    int x = 0;
                    if (s.equals("+")){
                        x = x1+x2;
                    } else if (s.equals("-")) {
                        x = x2-x1;//注意逆波兰表达式,先从栈中弹出的放在后面
                    } else if (s.equals("/")) {
                        x = x2/x1;
                    }else {
                        x = x1*x2;
                    }
                    stack.push(x);//计算之后放回栈中
                }else {
                    stack.push(Integer.parseInt(s));//将字符串转化为数字
                }
            }
            return stack.pop();//最后栈中的值就是最终的值
        }
		private boolean isOperation(String s){//判断是否为加减乘除
		            if (s.equals("+") ||s.equals("-")||s.equals("*")||s.equals("/")){
		                return true;
		            }
		            return false;
		        }
		    }

拓展: 中缀表达式转后缀表达式,现给出中缀表达式( 1 + 2 ) * ( 3 + 4 ),转为后缀(逆波兰)表达式过程如下.
在这里插入图片描述
其实我们在电脑中或者是手机上经常用到的计算器就是这样的原理.计算机中的计算器是无法直接识别中缀表达式的,都是先转为后缀表达式,再进行运算的.

在这里插入图片描述

2.3 入栈出栈顺序匹配

OJ链接

在这里插入图片描述

class Solution3 {
        public boolean validateStackSequences(int[] pushed, int[] popped) {
            Stack<Integer> stack = new Stack<>();
            int j = 0;
            for (int i = 0; i < pushed.length; i++) {
                stack.push(pushed[i]);
                while (!stack.empty() &&stack.peek() == popped[j]){//每放入栈中一个元素,就和popped比较是否相等
                    stack.pop();//如果相等,出栈
                    j++;//popped下标向后走
                }
            }
            while (j < popped.length){//i把push全部遍历完之后,Stack中可能还有元素没有与popped中的匹配完成
                if (stack.peek() == popped[j]){
                    stack.pop();
                    j++;//继续匹配操作
                }else {
                    return false;//一旦有一个不匹配,说明popped的出栈顺序是错误的
                }
            }
            return true;//全部匹配完成,返回true
        }
    }

2.4 在常数时间复杂度的情况下寻找栈中最小元素

OJ链接

在这里插入图片描述

class MinStack {
        Stack<Integer> stack;
        Stack<Integer> stack1;
        public MinStack() {
            stack = new Stack<>();//放所有要入栈的元素
            stack1 = new Stack<>();//放较小元素,栈顶元素是入stack所有元素中最小的
        }

        public void push(int val) {
            stack.push(val);
            if (stack1.empty()){//如果最小栈中没有元素,就把第一个元素放入
                stack1.push(val);
            }else{
                if(stack1.peek() >= val){//和最小栈的栈顶元素比较大小,stack1的栈顶大于等于val的时候,入栈
                    //等于的时候也要放入,否则pop的时候,最小栈和普通栈会不匹配
                    stack1.push(val);
                }
            }
        }

        public void pop() {
            if (Objects.equals(stack.pop(), stack1.peek())){
                stack1.pop();//两栈元素相等的时候都弹出,否则只弹出普通栈中的元素
            }
        }

        public int top() {
            return stack.peek();//返回普通栈栈顶元素
        }

        public int getMin() {
            return stack1.peek();//直接返回最小栈的栈顶元素
        }
    }

2.5 逆序打印列表

方法一:递归法

void printList(Node head){
    if(null != head){//遇到null的时候往回递归
        printList(head.next);//没有遇到null的时候,向后递归
        System.out.print(head.val + " ");
   }
}

图解:
在这里插入图片描述

方法二:Stack法

 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 + " ");
   }
}

从上述代码,我们可以得到一个结论,栈可以替代递归思想,在我们后期学习二叉树的时候,在非递归遍历二叉树的时候,我们会频繁地用到栈.

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

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

相关文章

STL常用容器(2)---vector容器

1.1 vector基本概念 功能&#xff1a; vector数据结构和数组非常相似&#xff0c;也称为单端数组 vector与普通数组区别&#xff1a; 不同之处在于数组是静态空间&#xff0c;而vector可以动态扩展 动态扩展&#xff1a; 并不是在原空间之后的续接的新空间&#xff0c;而…

腾讯云4核8G配置的服务器有哪些优惠?价格好不?

2024年腾讯云4核8G服务器租用优惠价格&#xff1a;轻量应用服务器4核8G12M带宽646元15个月&#xff0c;CVM云服务器S5实例优惠价格1437.24元买一年送3个月&#xff0c;腾讯云4核8G服务器活动页面 txybk.com/go/txy 活动链接打开如下图&#xff1a; 腾讯云4核8G服务器优惠价格 轻…

邀请媒体采访报道对企业宣传有何意义?

传媒如春雨&#xff0c;润物细无声的&#xff0c;大家好&#xff0c;我是51媒体网胡老师。 邀请媒体采访报道对企业宣传具有多重意义&#xff1a; 提升品牌知名度和曝光度&#xff1a;媒体是信息传播的重要渠道&#xff0c;通过媒体的报道&#xff0c;企业及其活动、产品能够…

SpringBoot整合Flowable/Activiti

SpringBoot版本: 2.0.1.RELEASE Flowable版本: 6.3.1 Activiti版本: 6.0.0 一.添加pom依赖 因为之前我整合的时候有报错关于sqlsession的错误,后面查询文章才发现flowable要排除掉mybatis,又没说具体排除哪一个,所以我这干脆全部排除了 <!-- Flowable dependencies -->…

Servlet 的基本理解

Servlet 是JavaEE规范的一种&#xff0c;主要是为了扩展Java作为Web服务的功能&#xff0c;统一接口。由其他内部厂商如tomcat&#xff0c;jetty内部实现web的功能。如一个http请求到来&#xff1a;容器将请求封装为servlet中的HttpServletRequest对象&#xff0c;调用init()&a…

Spring Security 实现后台切换用户

Spring Security version 后端代码&#xff1a; /*** author Jerry* date 2024-03-28 17:47* spring security 切换账号*/RestController RequiredArgsConstructor RequestMapping("api/admin") public class AccountSwitchController {private final UserDetailsSe…

即将截稿 CCF-A多媒体顶会ACM MM‘24 北京时间4月9日提交摘要

会议之眼 快讯 第32届ACM MM (ACM MULTIMEDIA)即国际多媒体会议将于 2024 年 10月28 -日11月1日在澳大利亚墨尔本隆重举行&#xff01;MM是由ACM&#xff08;Association for Computing Machinery&#xff0c;计算机协会&#xff09;主办的国际性学术会议&#xff0c;是计算机…

应对苹果商店审核失败:解决Flutter应用被拒绝的常见情况与解决方案

引言 Flutter是一款由Google推出的跨平台移动应用开发框架&#xff0c;其强大的性能和流畅的用户体验使其备受开发者青睐。然而&#xff0c;开发一款应用只是第一步&#xff0c;将其成功上架到苹果商店才是实现商业目标的关键一步。本文将详细介绍如何使用Flutter将应用程序上…

Day81:服务攻防-开发框架安全SpringBootStruts2LaravelThinkPHPCVE复现

目录 PHP-框架安全-Thinkphp&Laravel Laravel CVE-2021-3129 RCE Thinkphp 版本3.X RCE-6.X RCE 版本6.X lang RCE J2EE-框架安全-SpringBoot&Struts2 Struct2 旧漏洞(CVE-2016-0785等) struts2 代码执行 &#xff08;CVE-2020-17530&#xff09;s2-061 Str…

为什么要学习数学/科学史?

一、说明 哈代的经典著作《数学家的道歉》&#xff0c;他在书中为自己选择的数学职业辩护&#xff0c;他坦诚了自己一生贡献之微不足道。事实是&#xff0c;哈代没什么可道歉的。哈代是一位真正的顶级数学家&#xff0c;完全有资格获得他选择的头衔&#xff0c;并且以伯乐之能…

HarmonyOS NEXT应用开发之ForEach:循环渲染

ForEach接口基于数组类型数据来进行循环渲染&#xff0c;需要与容器组件配合使用&#xff0c;且接口返回的组件应当是允许包含在ForEach父容器组件中的子组件。例如&#xff0c;ListItem组件要求ForEach的父容器组件必须为 List组件 。 说明&#xff1a; 从API version 9开始&a…

蓝桥杯嵌入式备考笔记

keil配置 LED-KEY-LCD 留下这几个 按键 创建俩个文件写代码&#xff0c;记得把这两个文件加进工程 led uwTick 1ms执行一次 写错了 不是1000 是100 PD2 SET 表示打开锁存器 可以操作LED LED对应PC引脚拉高是熄灭 key 如果要在main使用需要extern LCD最多21位 …

C语言进阶课程学习记录-第21课 - 宏定义与使用分析

C语言进阶课程学习记录-第21课 - 宏定义与使用分析 宏定义的本质实验-字面量比较宏定义表达式实验-表达式有效性宏的作用域实验-作用域分析内置宏内置宏演示小结 本文学习自狄泰软件学院 唐佐林老师的 C语言进阶课程&#xff0c;图片全部来源于课程PPT&#xff0c;仅用于个人学…

012:vue3使用vue-i18n实现国际化

文章目录 1. 安装 vue-i18n2. 创建文件存储翻译的语言3. 注册i18n实例4. 在main.ts中引入vue-i18n实例5. 在组件模板中使用6. 在js中使用7. locale.value 实现国际化语言切换8. vue3 中ref里面的国际化值没生效问题 1. 安装 vue-i18n cnpm i --save vue-i18n2. 创建文件存储翻…

进销存管理系统:食品批发零售迈向数字化未来-亿发

随着消费逐步复苏&#xff0c;食品批发零售行业也迎来了客流的回升&#xff0c;实体店重新焕发了生机。然而&#xff0c;随着数字化时代的来临&#xff0c;传统的食品批发零售企业面临着新的挑战和机遇。些企业正积极实施数字化转型&#xff0c;通过布局线上线下多业态的融合发…

jQuery(一)

文章目录 1. 基本介绍2.原理示意图3.快速入门1.下载jQuery2.创建文件夹&#xff0c;放入jQuery3.引入jQuery4.代码实例 4.jQuery对象与DOM对象转换1.基本介绍2.dom对象转换JQuery对象3.JQuery对象转换dom对象4.jQuery对象获取数据获取value使用val&#xff08;&#xff09;获取…

翻译: 硅谷软件工程师面试:准备所需的一切

没有人有时间去做成百上千道LeetCode题目&#xff0c;好消息是你实际上并不需要做那么多题目就能够在FAANG公司找到工作&#xff01; 我曾经在Grab工作&#xff0c;这是东南亚的一家共享出行公司&#xff0c;但我对工作感到沮丧&#xff0c;想要进入FAANG公司&#xff0c;但我…

编译好的C++应用程序拷贝到其它电脑,提示dll未找到依赖项的解决方法。

编译好的C应用程序拷贝到其它电脑上&#xff0c;运行时出现提示dll未找到依赖项。 由于dll依赖于其它dll&#xff0c;在开发用电脑上的环境不能完全与其它电脑相同。 解决办法是找到调用到的dll依赖的所有dll&#xff0c;拷贝到运行目录下。 在开发电脑上&#xff1a; 1、开…

一款功能强大且易于使用的视频剪辑应用程序

一款功能强大且易于使用的视频剪辑应用程序&#xff0c;它提供了丰富多样的转场特效和滤镜&#xff0c;让用户能够轻松地为视频添加各种炫酷的效果。与其他视频编辑软件相比&#xff0c;剪映国际版的最大亮点在于其完全免费使用。首先&#xff0c;剪映国际版为用户提供了丰富的…

ChatGPT/GPT4科研应用与绘图技术及论文写作

2023年随着OpenAI开发者大会的召开&#xff0c;最重磅更新当属GPTs&#xff0c;多模态API&#xff0c;未来自定义专属的GPT。微软创始人比尔盖茨称ChatGPT的出现有着重大历史意义&#xff0c;不亚于互联网和个人电脑的问世。360创始人周鸿祎认为未来各行各业如果不能搭上这班车…