了解栈Stack一篇文章就够了

news2025/1/24 17:48:34
  1. 什么是栈

栈是一种特殊的线性表,只允许一端进行数据的插入和删除,即先进后出原则。类似于弹夹先装进去的子弹后面出,后放入的子弹先出。

  1. 栈的底层原理

栈是一种线性结构,所以既能使用数组实现,也能使用链表实现,我就采用数组的方法实现一下栈
public class MyStack {
    public int[] elem;
    private static final int DEFAULT_CAPACITY = 10;
    public MyStack() {
        elem = new int[DEFAULT_CAPACITY];
    }
    //既能统计栈中存储多少个有效数据,也可以作为存放元素的下标
    public int usedSize;
    //压栈
    public void push(int val) {
        //先判满,如果满了要扩容
        if(isFull()) {
            elem = Arrays.copyOf(elem, elem.length * 2);
        }
        elem[usedSize] = val;
        usedSize++;
    }

    private boolean isFull() {
        return usedSize == elem.length;
    }
    //出栈
    public int pop() {
        //先判空,如果栈为空抛出异常
        if(empty()) {
            throw new EmptyArrayException("栈为空");
        }
        int val = elem[usedSize-1];
        usedSize--;
        return val;
    }

    private boolean empty() {
        return usedSize == 0;
    }
    //查看栈顶元素
    public int peek() {
        if(empty()) {
            throw new EmptyArrayException("栈为空");
        }
        return elem[usedSize-1];
    }
    //获取栈中有多少元素
    public int getUsedSize() {
        return usedSize;
    }
}
使用数组的实现方式,入栈只需要elem[usedSize] = data和出栈只需要usedSize--的时间复杂度都是O(1)。
如果使用单向链表,采用头插法入栈和出栈,只需要移动head头节点,时间复杂度也是O(1);要是采用尾插法入栈和出栈,入栈和出栈都需要从头节点出发,走到尾巴,才能完成元素的入栈或出栈,时间复杂度为O(n).
如果是双向链表,那么一个节点即知道后继节点,也知道前驱节点,有头节点head也有尾节点tail,采用头插法进行入栈和出栈只需要移动head头节点,采用尾插法进行入栈和出栈也是一样,只需要移动tail尾巴节点。
  1. 栈的可能出栈顺序

题目:若入栈序列为1,2,3,4,进栈的过程中可以出栈,则下面不可能的出栈序列是哪个?

A.1,4,3,2 B.2,3,4,1 C.3,1,4,2 D.3,4,2,1
方法:按题目给的入栈顺序,结合选项,加画图(熟练以后不用画图)
A选项:第一个出栈是1,所以1进栈后出栈,2进栈,3进栈(因为出栈的第二个是4,所以2,3没有出栈),4进栈。4出栈,3出栈,2出栈。所以A是可能的出栈序列
B选项:B选项第一个出栈的是2,所以1进栈2进栈,2出栈,3进栈3出栈,4进栈4出栈,此时栈还剩1,1出栈。也是可能的出栈序列
C选项:你看C选项第一个出栈的是3,所以1,2,3都进栈,3再出栈,它第二个出栈的是1,但是此时栈顶元素是2,所以这是不可能的出栈顺序
D选项:第一个出栈的是3,所以要1,2,3都入栈了,3是栈顶元素才能出栈,接着4入栈,4又出栈,然后把栈中2出栈,1出栈

有关出栈顺序的oj题: https://www.nowcoder.com/practice/d77d11405cc7470d82554cb392585106?tpId=13&&tqId=11174&rp=1&ru=/activity/oj&qru=/ta/coding-interviews/question-ranking

public class Solution {
    public boolean IsPopOrder(int [] pushA, int [] popA) {
        Stack<Integer> stack = new Stack<>();
        int index = 0;//popA数组下标
        //遍历压栈pushA数组
        for (int i = 0; i < pushA.length; i++) {
            stack.push(pushA[i]);
            //如果栈顶元素和popA[index]相等
            //并且要防止栈为空(空指针异常)和数组越界
            //使用循环可能连着多个相等
            while (!stack.empty() && index < popA.length && stack.peek() == popA[index]) {
                stack.pop();
                index++;
            }
        }
        //如果是可能的出栈序列,那么栈中的元素能全部匹配,全部被弹出
        //如果栈不为空,说明是不可能的出栈序列
        return stack.empty();
    }
}
  1. 中缀表达式转后缀表达式

题目1:中缀表达式:2+3*6的后缀表达式?
题目2 :中缀表达式:(2+3)*5的后缀表达式
中缀转后缀,我们是加括号,然后把操作符移到对应括号后面,再去括号。同理,中缀转前缀,就是把操作符移到括号前面
  1. 求后缀表达式/逆波兰表达式的计算结果

力扣Oj: https://leetcode.cn/problems/evaluate-reverse-polish-notation/

解决方法:使用栈,将数字放入栈中,如果碰到操作符,取出栈顶的2个元素,第一个取出的放操作符右边,第二个取出放操作符左边(固定的),计算完了再放入栈中,直到遍历完该字符串数组,此时栈中元素的值就是结果
class Solution {
    public int evalRPN(String[] tokens) {
        //等会要进行运算,类型用Integer
        Stack<Integer> stack = new Stack<>();
        //遍历数组
        for(String x: tokens) {
            //判断是不是数字字符串
            if(! isOperation(x)) {
                //如果是数字字符串,入栈
                stack.push(Integer.parseInt(x));//转为数字
            }else {
                //碰到操作符,出栈2个数
                int num1 = stack.pop();
                int num2 = stack.pop();
                //根据不同操作字符,进行运算,第一个弹出放操作符右边,第二个放左边
                //运算完后,重新入栈
                switch(x) {
                    case "+" :
                        stack.push(num2 + num1);
                        break;
                    case "-" :
                        stack.push(num2 - num1);
                        break;
                    case "*":
                        stack.push(num2 * num1);
                        break;
                    case "/" :
                        stack.push(num2 / num1);
                        break;
                } 
            }
        }
        //此时栈中元素就是运算结果
            return stack.pop();
    }
    private boolean isOperation(String x) {
        //字符串比较不能使用==,==是比较地址,而不是比较值
        //字符串重写了Object类的equals()方法,是比较值的
        if(x.equals("+") || x.equals("-") || x.equals("*") || x.equals("/")) {
            return true;//如果是操作符返回真
        }
        return false;//不是返回假
    }
}

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

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

相关文章

【蓝桥杯刷题训练营】day05

1 数的分解 拆分成3个数相加得到该数 然后采用了一种巨愚蠢的办法&#xff1a; int main() {int count 0;int a 2;int b 0;int c 1;int d 9;int a1, a2, a3;int c1, c2, c3;int d1, d2, d3;for (a1 0; a1 < 2; a1){for (a2 0; a2 < 2; a2){for (a3 0; a3 <…

中断和事件

目录 中断概述 什么是中断&#xff1f; 什么是EXTI&#xff1f; EXTI初始化结构体&#xff1a; 中断/事件线&#xff1a; EXTI模式&#xff1a; 触发类型&#xff1a; EXTI控制&#xff1a; 什么是优先级&#xff1f; 什么是优先级分组&#xff1f; 什么是NVIC&#…

【Java】最新版本SpringCloudStream整合RocketMQ实现单项目中事件的发布与监听

文章目录前言依赖配置代码参考前言 SpringCloud项目中整合RocketMQ是为了削峰填谷。 这里我使用RocketMQ的作用用于接收项目中产生的消息&#xff0c;然后异步的发送邮件给客户&#xff0c;这是这个项目的产生的背景。 依赖配置 <dependencies><dependency><…

开发钉钉微应用,实现免登+调试

1.创建h5微应用 https://open.dingtalk.com/document/orgapp/develop-org-h5-micro-applications 根据里面的三个步骤,创建h5微应用 2.免登之前必须要先进行JSAPI的授权 文档说明: https://open.dingtalk.com/document/orgapp/jsapi-authentication 根据文档中的说明 步骤…

spring事物源码分析

今天的任务是剖析源码&#xff0c;看看Spring 是怎么运行事务的&#xff0c;并且是基于当前最流行的SpringBoot。还有&#xff0c;我们之前剖析Mybatis 的时候&#xff0c;也知道&#xff0c;Mybatis 也有事务&#xff0c;那么&#xff0c;他俩融合之后&#xff0c;事务是交给谁…

MySQL (六)------MySQL的常用函数、 事务(TCL)、DCL用户操作语句、常见环境、编码问题

第一章 MySQL的常用函数 1.1 字符串函数 1.1.1 字符串函数列表概览 函数用法CONCAT(S1,S2,......,Sn)连接S1,S2,......,Sn为一个字符串CONCAT_WS(separator, S1,S2,......,Sn)连接S1一直到Sn&#xff0c;并且中间以separator作为分隔符CHAR_LENGTH(s)返回字符串s的字符数LENGTH…

深入理解性能压测工具原理

如果没有性能测试工具如何通过手工实现 如果没有性能测试工具&#xff0c;通过手工进行性能测试&#xff0c;这是一个值得我们思考的问题。这时候需要一个协调员发送指令&#xff0c;一个操作员进行操作&#xff0c;对系统施加压力&#xff0c;多个操作员代表着多个用户进行并…

面向对象设计模式:创建型模式之原型模式

文章目录一、引入二、代理模式&#xff0c;Prototype Pattern2.1 Intent 意图2.2 Applicability 适用性2.3 类图2.4 应用实例&#xff1a;使用下划线或消息框展示字符串2.4 应用实例&#xff1a;JDK java.lang.Object java.lang.Cloneable一、引入 二、代理模式&#xff0c;Pr…

Python—看我分析下已经退市的 可转债 都有什么特点

分析 需求分析 可转债退市原因的种类与占比是多少 强赎与非强赎导致的退市可转债 存续时间 维度占比 强赎与非强赎导致的退市可转债 发行资金 规模占比 强赎与非强赎导致的退市可转债 各个评级 的占比 强赎与非强赎导致的退市可转债 各个行业&#xff08;一级行业&#xf…

互相关延时估计 Matlab仿真

文章目录互相关延时估计什么是互相关延时估计&#xff1f;原理代码实现总结互相关延时估计 互相关延时估计是一种信号处理技术&#xff0c;用于计算两个信号之间的时间延迟。在本篇博客中&#xff0c;我们将使用MATLAB来实现互相关延时估计&#xff0c;并提供多个例子和代码&a…

TypeScript深度剖析: TypeScript 中函数的理解?与 JavaScript 函数的区别?

一、是什么 函数是 JavaScript 应用程序的基础&#xff0c;帮助我们实现抽象层、模拟类、信息隐藏和模块 在 TypeScript 里&#xff0c;虽然已经支持类、命名空间和模块&#xff0c;但函数仍然是主要定义行为的方式&#xff0c;TypeScript 为 JavaScript 函数添加了额外的功能…

English Learning - L2-5 英音地道语音语调 弹力双元音 [ɪə] [ʊə] [eə] 2023.03.6 周一

English Learning - L2-5 英音地道语音语调 弹力双元音 [ɪə] [ʊə] [eə] 2023.03.6 周一朗读节奏元音的长度元音发音在清辅音和浊辅音前的区别元音发音跟后面浊辅音节数的区别元音在重读音节中复习大小元音发音对比/ʌ/ 舌中音/ɒ/ 舌后音/ʊ/ 舌后音/ɪ/ 舌前音[ɑ:] VS […

Jenkins+Docker自动化部署项目

看到了一篇文章&#xff0c;实操一下自动部署的感觉。参看地址&#xff1a;原文 首先更新docker&#xff0c;我更新到了 [rootlocalhost springboot]# docker --version Docker version 23.0.1, build a5ee5b1跟新步骤&#xff1a; yum update#卸载旧版本 yum remove dock…

Nginx支持quic协议

第一种方式&#xff1a;Nginx官方nginx-quic搭建 通过部署Nginx官方的QUIC分支来实现的浏览器和nginx-quic服务器粗略的HTTP3通信。 1、下载BoringSSL BoringSSL 是由谷歌开发,从 OpenSSL 中分离的一个分支。BoringSSL 是 Chrome/Chromium、Android&#xff08;但它不是 NDK 的…

Spark Yarn 运行环境搭建

文章目录Spark Yarn 运行环境搭建1、解压缩文件2、修改配置环境文件3、配置历史服务器Spark Yarn 运行环境搭建 1、解压缩文件 将spark3.2.3的压缩包上传到 linux /opt/software 目录下 输入命令&#xff1a; tar -zxvf spark-3.2.3-bin-hadoop3.2-scala2.13.tgz -C /opt/ 解…

究竟是谁负了谁,来自底层测试的2022年终总结

前言 说实话坐在椅子前&#xff0c;都想好了&#xff0c;该怎么去写&#xff0c;甚至感觉有好多要写的&#xff0c;但是当我坐在椅子上时&#xff0c;却不知道该怎么开头了&#xff0c;不知道是不是紧张&#xff1f;还是不舍&#xff1f;难道还没有跟过去挥手告别的勇气吗&…

lambda函数

Lambda(函数指针)lambda 是c11非常重要也是最常用的特性之一&#xff0c;他有以下优点&#xff1a;可以就地匿名定义目标函数或函数对象&#xff0c;不需要额外写一个函数lambda表达式是一个匿名的内联函数lambda表达式定义了一个匿名函数&#xff0c;语法如下&#xff1a;[cap…

Vue3手写分页在分页的基础上用到Pagination 分页组件

近期有个项目要用到分页组件&#xff0c;但是内容不是表格&#xff0c;所以自己就研究了一下在Pagination 分页组件的基础上手写了分页 效果图&#xff1a; 目录 一、先声明几个变量用来定义第几页&#xff0c;每页多少条&#xff0c;总页数。 二、然后封装一个函数方便以后…

学习 Python 之 Pygame 开发魂斗罗(十)

学习 Python 之 Pygame 开发魂斗罗&#xff08;十&#xff09;继续编写魂斗罗1. 解决敌人不开火的问题2. 创建爆炸效果类3. 为敌人跳入河中增加爆炸效果4. 玩家击中敌人继续编写魂斗罗 在上次的博客学习 Python 之 Pygame 开发魂斗罗&#xff08;九&#xff09;中&#xff0c;…

pycharm 使用方式

提示&#xff1a; pycharm 是专业版&#xff1b; 社区版目前暂不支持调试 Jupyter; 如果你是学生&#xff0c; 在读期间&#xff0c;每一年可以申请免费一年使用专业版&#xff0c; 详情到Jetbrain 去申请&#xff1b; 在申请过程中&#xff0c;需要注意&#xff0c; 不要使用…