Java - 数据结构,栈

news2024/9/28 19:20:14

一、栈

1.1、什么是栈

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

什么是Java虚拟机栈?
在这里插入图片描述
java虚拟机栈也是栈,就是JVM中的一块内存,也是符合栈的规则 – 先进后出规则

方法区:存放类定义信息、字节码、常量等数据,在Sun HotSpot JVM中,这块也称为Perm Gen。

堆:创建的对象信息将放入堆中,堆内部如何实现各虚拟机各不相同,对于Sun HotSpot JVM来说又分为Young Gen和Tenured Gen,更详细描述参见《[Java性能剖析]Sun JVM内存管理和垃圾回收 》

Java栈:对于每个执行线程,会分配一个Java栈,JVM在执行过程当中,每执行一个方法,都会为方法在当前栈中增加一个栈帧,每个栈帧的信息与具体实现相关,但一般会由3部分组成:变量区,方法参数和本地变量会放入这个位置,大小是固定的,在进行方法时会先分配好,在类定义中,会由max local来指定这块区的大小;方法信息区,会包括当前类常量池的入口地址等信息,这块大小也是固定的;操作栈,与Intel体系架构中的运算使用寄存器来进行不一样,JVM的字节码的方法调用、运算等需要的参数,都是通过操作栈来传递的。在类定义中,会由max stack指定最大的操作栈。关于Java栈的更详细描述参见《Java 栈内存介绍 》

本地方法栈:对本地方法的调用,并不会使用Java栈而是使用本地方法栈,本地方法栈的组成取决于所使用的平台和操作系统.

PC寄存器/程序计数器:对于每个执行线程会分配一个PC寄存器,寄存器中存放当前字节码的执行位置

什么是栈帧?
调用函数的时候,我们会为函数开辟一块内存,这块内存叫做栈帧,这个内存在Java虚拟机栈中开辟

2.2、栈的笔试题

2.2.1、一个栈的输入顺序是ABCDEF,那么不可能出现的出栈顺序是什么()

A、DCBAEF

B、ACBEDF

C、DEFBCA

D、CDBAFE

在出栈的时候可以入一个出一个,入栈和出栈的顺序可以打乱,但是出栈的时候,一定是先出栈顶的元素
在这里插入图片描述

剑指 Offer 31. 栈的压入、弹出序列

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

public boolean validateStackSequences(int[] pushed, int[] popped) {
        Stack<Integer> stackA = new Stack<Integer>();
        int j = 0;
        //遍历数组pushed
        for(int i = 0; i < pushed.length; i++){
            stackA.push(pushed[i]);

            //判断栈顶元素是否和popped数组的j下标相等,如果相等就出栈
            while(j < popped.length && !stackA.empty() && stackA.peek() == popped[j]){
                stackA.pop();
                j++;
            }    
        }

        return stackA.empty();
    }

2.2.2、中缀表达式转后缀表达式

它们都是对表达式的记法,因此也被称为前缀记法、中缀记法和后缀记法。它们之间的区别在于运算符相对与操作数的位置不同:前缀表达式的运算符位于与其相关的操作数之前;中缀和后缀同理。

举例:
(3 + 4) × 5 - 6 就是中缀表达式

-× + 3 4 5 6 前缀表达式

3 4 + 5 × 6 - 后缀表达式

中缀表达式(中缀记法)
中缀表达式是一种通用的算术或逻辑公式表示方法,操作符以中缀形式处于操作数的中间。中缀表达式是人们常用的算术表示方法。
虽然人的大脑很容易理解与分析中缀表达式,但对计算机来说中缀表达式却是很复杂的,因此计算表达式的值时,通常需要先将中缀表达式转换为前缀或后缀表达式,然后再进行求值。对计算机来说,计算前缀或后缀表达式的值非常简单。

前缀表达式(前缀记法、波兰式)
前缀表达式的运算符位于操作数之前。

后缀表达式(后缀记法、逆波兰式)
后缀表达式与前缀表达式类似,只是运算符位于操作数之后。

如何将中缀表达式转换成后缀表达式
在这里插入图片描述

利用栈实现计算后缀表达式的值:逆波兰表达式求值

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

class Solution {
    public int evalRPN(String[] tokens) {
        Stack<Integer> stack = new Stack<>();
        for(int i = 0; i < tokens.length; i++){
            String val = tokens[i];
            if(isOperator(val) == false){
                stack.push(Integer.parseInt(val));
            }else {
                int num2 = stack.pop();
                int num1 = stack.pop();
                switch (val){
                    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();
    }
    //判断是不是运算符,是就返回true,不是就返回FALSE
    private boolean isOperator(String val){
        if(val.equals("+") || val.equals("-") || val.equals("*") || val.equals("/")){
            return true;
        }
        return false;
    }
}

2.3、栈的方法

push(); -- 添加元素

public static void main(String[] args) {
        Stack<Integer> stack = new Stack<>();
        stack.push(1);
        stack.push(2);
        stack.push(3);
        stack.push(4);
        System.out.println(stack);
        System.out.println(stack.pop());
        System.out.println(stack);
        stack.peek();
        System.out.println(stack);
    }

2.4、模拟实现一个栈

在这里插入图片描述

public class MyStack {
    public int elem[];
    public int usedSize;

    public MyStack(){
        //源码中默认大小为10
        this.elem = new int[10];
    }

    //添加元素
    public void push(int val){
        //判断是否满
        if(isFull()){
            //如果满了就要扩容,
            this.elem = Arrays.copyOf(elem, 2*this.usedSize);
        }
        this.elem[this.usedSize] = val;
        this.usedSize++;
    }
    private boolean isFull(){
        //满了返回true
        return this.elem.length == this.usedSize;
    }

    //出栈
    public int pop(){
        //首先要判断栈里面有没有元素
        if(empty()){
            //如果没有元素就不能出栈,此时就要抛出异常
            throw new RuntimeException("栈为空!");
        }
        //如果有元素就可以出栈了
        int oldVal = this.elem[usedSize-1];
        //如果栈里面存的是引用类型,那这个就要置位null
        usedSize--;
        return oldVal;
    }

    public boolean empty(){
        return this.usedSize == 0;
    }

    //获取栈顶元素
    public int peek(){
        //首先要判断栈里面有没有元素
        if(empty()){
            //如果没有元素就不能出栈,此时就要抛出异常
            throw new RuntimeException("栈为空!");
        }
        return this.elem[usedSize-1];
    }
    
}

面试题:能不能用单链表实现一个栈

首先,要实现一个栈,就要知道栈的特点
1、先进后出
2、入栈和出栈的时间复杂度是O(1)
那单链表呢,单链表可以头插和尾插,那用头插还是插???
如果用头插:在入栈的时候就头插,时间复杂度也是O(1),出栈的时候只要删除头结点,时间复杂度也是O(1)。
如果用尾插:那就不可能实现,在插入的时候可以用尾插,时间复杂度是O(1),但是在出栈的时候就不行了,在删除尾巴节点的时候,要知道尾巴节点的前驱才能删除,但是这时候就要遍历一遍链表,时间复杂度就是O(n)

那单链表不行,就可以使用双向链表。

有效的括号

给定一个只包括 ‘(’,‘)’,‘{’,‘}’,‘[’,‘]’ 的字符串 s ,判断字符串是否有效。
有效字符串需满足:
左括号必须用相同类型的右括号闭合。
左括号必须以正确的顺序闭合。
每个右括号都有一个对应的相同类型的左括号。

/在做这道题的时候要考虑几种情况
    //1、左括号多了 (((  ))
    //2、右括号多了 (((((  ))
    //2、括号不匹配  ( [ ] } 
    public boolean isValid(String s) {
        //栈里面存放的是左括号
        Stack<Character> stack = new Stack<>();
        char[] chars = s.toCharArray();
        for(int i = 0; i < chars.length; i++){
            if(chars[i] == '[' || chars[i] == '(' || chars[i] == '{'){
                stack.push(chars[i]);
            }else{
                if(stack.empty()){
                    //右括号多了
                    return false;
                }else{
                    if((chars[i] == '}' && stack.peek() == '{') || (chars[i] == ']' && stack.peek() == '[') || (chars[i] == ')' && stack.peek() == '(')){
                        stack.pop();
                    }else{
                        //括号不匹配
                        return false;
                    }
                }
            }

        }

        if(!stack.empty()){
            //右括号多了
            return false;
        }
        return true;
    }

最小栈

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

实现 MinStack 类:

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

 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.empty() ){
            minStack.push(val);
        }else{
            if(val <= minStack.peek()){
                minStack.push(val);
            }
        }
    }
    
    public void pop() {
        int popVal = stack.pop();
        if(!minStack.empty()){
            if(popVal == minStack.peek()){
                minStack.pop();
            }
        }
    }
    
    public int top() {
        return stack.peek();
    }
    
    public int getMin() {
        return minStack.peek();
    }

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

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

相关文章

关于《How to Learn to Code Get a Developer Job in 2023》的经验学习

1. Who is This Book For ? for Anyone who is considering a career in software development. 2. Can Anyone Learn to Code? Any sufficiently motivated person can learn to code. 3.Executive Summary Learning to code is hard.Getting a job as a software devel…

01-基于SOA架构someip 开发-Linux开发环境搭建

前言&#xff1a;SOME/IP 是一个汽车的中间件解决方案&#xff0c;可用于控制消息。从一开始&#xff0c;它的设计就是为了完美地适应不同尺寸和不同操作系统的设备。这包括小型设备&#xff0c;如相机、AUTOSAR设备&#xff0c;以及头部单元或远程信息处理设备。同时还确保了S…

华为OD机试题,用 Java 解【VLAN 资源池】问题

最近更新的博客 华为OD机试 - 猴子爬山 | 机试题算法思路 【2023】华为OD机试 - 分糖果(Java) | 机试题算法思路 【2023】华为OD机试 - 非严格递增连续数字序列 | 机试题算法思路 【2023】华为OD机试 - 消消乐游戏(Java) | 机试题算法思路 【2023】华为OD机试 - 组成最大数…

脑洞|ChatGPT加持下,ChatOps将如何革新团队协作与运维管理?

要说近期科技圈 “顶流”&#xff0c;非 ChatGPT 莫属。 比起目前常见的语音助手与聊天 bot&#xff0c;这位机器人显得更有 “人味儿”&#xff0c;不仅能模拟人类的语气&#xff0c;跟你聊得有来有回&#xff0c;还能写剧本、编音乐、写代码。 说到聊天工具&#xff0c;就让…

低代码开发可以解决哪些问题?

低代码开发可以解决哪些问题&#xff1f;如果用4句话去归纳&#xff0c;低代码开发可以解决以下问题—— 为企业提供更高的灵活性&#xff0c;用户可以突破代码的限制自主开发业务应用&#xff1b;通过减少对专业软件开发人员的依赖&#xff0c;公司可以快速响应市场上的新业务…

完全背包—动态规划

一、背包问题概述 如图&#xff0c;完全背包与01背包的区别只有一点&#xff1a;01背包中每个物品只能取一个而完全背包中每个物品可以取无数个。解决完全背包问题必须首先弄明白01背包&#xff0c;不清楚的可以看我的这篇文章01背包—动态规划。 二、例题 重量价值物品0115物…

Jenkins+docker发布Springbot服务

1.开发Springbot应用 新建多个环境的配置文件 bootstrap.yaml 通过变量获取不同环境active bootstrap-dev.yml bootstrap-pre.yaml 预发布及生产环境配置文件走nacos 二.配置docker 新增Dockerfile文件 Dockerfile内容 # Docker image for springboot file run # VERSION…

代码名命规范浅析

日常开发编码中&#xff0c;代码的名命是个大学问&#xff0c;能快速的看懂开源代码的结构和意图&#xff0c;也是一项必备的能力。在java项目的代码结构中&#xff0c;采用长名命的方式来规范类的名命&#xff0c;能够自己表达其主要意图&#xff0c;配合高级IDE&#xff0c;可…

万字长文带你实战 Elasticsearch 搜索

ES 高级实战 前言 上篇我们讲到了 Elasticsearch 全文检索的原理《别只会搜日志了,求你懂点原理吧》,通过在本地搭建一套 ES 服务,以多个案例来分析了 ES 的原理以及基础使用。这次我们来讲下 Spring Boot 中如何整合 ES,以及如何在 Spring Cloud 微服务项目中使用 ES 来…

考研复试机试 | C++ | 王道机试课程笔记

目录Zero-complexity (上交复试题)题目&#xff1a;代码&#xff1a;括号匹配问题题目&#xff1a;代码&#xff1a;表达式解析问题 &#xff08;浙大机试题&#xff09;题目&#xff1a;代码&#xff1a;标准库里提供了栈 stack<typename> myStack .size() 栈的大小 .pu…

互斥信号+任务临界创建+任务锁

普通信号量 1、信号量概念 2、创建信号量函数 3、互斥信号量 创建互斥信号量函数 等待信号量函数 释放互斥信号量 4、创建任务临界区 5、任务锁 任务上锁函数 ​编辑 任务结束函数 效果 普通信号量 1、信号量概念 信号量像是一种上锁机制&#xff0c;代码必须获…

Java性能-回收算法-Throughout回收算法

垃圾回收算法 理解Throughput回收器 回收器三个基本操作——回收 找到不使用的对象 释放内存 压缩堆碎片 Minor GC和Full GC&#xff0c;每个操作都会标记&#xff0c;释放和压缩对应的目标分代 [63.205s][info][gc,start ] GC(13) Pause Full (Ergonomics) [63.205s][info][…

Odoo丨Odoo框架源码研读三:异常处理与定制化开发

Odoo丨Odoo框架源码研读三&#xff1a;异常处理与定制化开发 Odoo源码研读的第三期内容&#xff1a;异常处理与定制化开发。 *异常处理* Odoo中的Exception是对Python内置异常做了继承和封装&#xff0c;设定了自己核心的几个Exception。 而对异常的处理和Python内置异常的…

【趋势分析方法三】MATLAB代码实现TFPW-MK检验

目前水文时间序列趋势分析的方法很多&#xff0c;主要分为参数检验和非参数检验两大类&#xff1a; 参数检验中常用的有线性回归法、滑动平均法、累积距平法等非参数检验则主要包括Mann-Kendal&#xff08;MK&#xff09;法和 Spearman 秩次相关法等 虽然从理论上讲&#xff…

2023年,什么行业更有发展前景?

关于有前景有发展的行业推荐&#xff0c;小课今天还是推荐咱们IT互联网行业。 很多人会说现在懂电脑的那么多,这个行业都饱和了,很多学电脑的找不到工作都改行了。但事实是现在每个行各业都需要互联网&#xff0c;需要懂电脑的技术人才&#xff0c;尤其是在云计算、大数据到来…

了解一下TCP/IP协议族

在《简单说说OSI网络七层模型》中讲到&#xff0c;目前实际使用的网络模型是 TCP/IP 模型&#xff0c;它对 OSI 模型进行了简化&#xff0c;只包含了四层&#xff0c;从上到下分别是应用层、传输层、网络层和链路层&#xff08;网络接口层&#xff09;&#xff0c;每一层都包含…

《安富莱嵌入式周报》第304期:开源硬件耳机设计,AI单片机STM32N6已确定为M55内核,另外还有新品STM32H5, H50X, H7R, H7S发布

往期周报汇总地址&#xff1a;嵌入式周报 - uCOS & uCGUI & emWin & embOS & TouchGFX & ThreadX - 硬汉嵌入式论坛 - Powered by Discuz! 更新一期视频教程&#xff1a; 第6期ThreadX视频教程&#xff1a;图文并茂吃透RTOS运行机制&#xff0c;任务管理&…

微信小程序的全局弹窗以及全局实例

全局组件 微信小程序组件关系中&#xff0c;父组件使用子组件需要在父组件index.json中引入子组件&#xff0c;然后在父组件页面中使用&#xff0c;这种组件的对应状态是一对一的&#xff0c;一个组件对应一个页面。如果有一个全局弹窗&#xff08;登录&#xff09;&#xff0…

拒绝select *,Navicat快捷查询表中所有字段以,隔开两种方式【附带阿里开发手册】

一、前言 今天公司规定了不要使用SELECT *进行查询&#xff0c;让我想到阿里的《Java 开发手册》 中的ORM 映射规范也是这样的&#xff0c;于是翻出来看看&#xff0c;刚刚好重温一下&#xff01; 规范看了一定要实践&#xff0c;严格规范自己的代码风格&#xff0c;做一个优…

TEMU联盟计划用意何在?做推广达人真的能收入满满吗?

据东哥近期了解&#xff0c;Temu在北美市场表现十分火爆&#xff0c;甚至冲上了AppStore下载榜第一名。Temu在美国市场上采用了类似PDD的病毒式传播策略&#xff0c;以实惠的产品和折扣吸引消费者并动员普通人大量传播链接和App下载&#xff0c;所以有了TEMU联盟计划&#xff0…