Java数据结构-栈

news2024/11/25 18:41:37

目录

  • 1. 栈的概念
  • 2. 栈的实现
    • 2.1 顺序栈
    • 2.2 链式栈
  • 3. 栈的应用
    • 3.1 栈的使用
    • 3.2 括号匹配
    • 3.3 逆波兰表达式求值
    • 3.4 出栈入栈次序匹配
    • 3.4 最小栈

1. 栈的概念

栈是一种顺序结构,只允许在一端进行插入和删除,插入删除的一端叫栈顶,另一端叫栈底。栈是一种先进后出(后进先出)的数据结构。插入数据的操作叫入栈,删除数据的操作叫出栈。
在这里插入图片描述

2. 栈的实现

栈的实现有两种,一种是顺序栈,底层是数组;另一种是链式栈,是用链表实现的。栈的主要功能有:push(入栈)、pop(出栈)、peek(获取栈顶元素,不删除)、empty(判断栈是否为空)

2.1 顺序栈

使用数组实现,定义curSize记录当前数据的个数,如果空间满了,通过copyOf方法扩容

public class myStack<E> {
    public Object[] arr;//存放数据的数组
    public int curSize;//当前数据的个数

    public myStack() {
        this.arr = new Object[10];
    }

    //入栈
    public E push(E val) {
        //满了,扩容
        if (curSize == arr.length) {
            this.arr = Arrays.copyOf(this.arr, 2 * this.arr.length);
        }
        arr[curSize] = val;
        curSize++;

        return val;//返回入栈的元素
    }

    //出栈
    public E pop() {
        if (empty()) {
        	//如果栈中为空
            return null;
        }
        Object ret = this.arr[curSize - 1];
        curSize--;
        return (E) ret;//返回出栈的元素
    }

    //获取栈顶元素,不删除
    public E peek() {
        if (curSize == 0) {
            return null;
        }
        Object ret = this.arr[curSize - 1];
        return (E) ret;//返回栈顶元素
    }

    //判断是否为空
    public boolean empty() {
        return curSize == 0;
    }
}

2.2 链式栈

如果用单链表实现栈,只能在链表的头部进行操作,这样时间复杂度才为O(1);如果使用的是双向链表,头部和尾部都可以,这里我们使用单链表实现

public class myStack<E> {

	//链表的结点
    static class ListNode {
        public Object val;//数据
        public ListNode next;//下一个结点

        public ListNode(Object val) {
            this.val = val;
        }
    }

    public ListNode head;//(头结点)第一个结点

    //入栈
    public E push(E val) {
        ListNode newNode = new ListNode(val);
        if (head != null) {
            newNode.next = head;
        }
        head = newNode;
        return val;
    }

    //出栈
    public E pop() {
        if (head == null) {
            return null;
        }
        Object ret = head.val;

        if (head.next == null) {
            head = null;
            return (E) ret;
        }


        head = head.next;


        return (E) ret;
    }

    //获取栈顶元素
    public E peek() {
        if (head == null) {
            return null;
        }
        return (E) head.val;
    }

    //判断栈是否为空
    public boolean empty() {
        if (head == null) {
            return true;
        }
        return true;
    }

}

3. 栈的应用

3.1 栈的使用

在Java中,stack继承于Vector,实现了List接口
在这里插入图片描述
Java中stack的方法如下
在这里插入图片描述
search返回栈中某个元素举例栈顶的距离,如果该元素就是栈顶元素返回1,如果栈中不包含该元素,返回-1,如图
在这里插入图片描述

3.2 括号匹配

在这里插入图片描述

题目链接:有效的括号
题目要求: 给定字符串,字符串中只包含(){ } [ ],判断字符串中的括号是否能够匹配成功
解题思路: 遍历字符串,如果该字符是左括号就入栈,如果是右括号,看当前栈顶的元素是否与它匹配,如果匹配则将栈顶元素出栈;如果不匹配说明整个字符串都不匹配,此时返回false
匹配成功的条件是:字符串遍历结束并且栈为空
在这里插入图片描述
代码:

class Solution {
    public boolean isValid(String s) {
        Stack<Character> stack = new Stack<>();//创建字符类型的栈
        for (int i = 0; i < s.length(); i++) {
            char ch = s.charAt(i);//获取i下标的字符
            if (ch == '(' || ch == '{' || ch == '[') {
            	//如果是左括号,入栈
                stack.push(ch);
            } else {
            	//i下标是右括号
                //栈为空,返回
                if (stack.empty()) {
                    return false;
                }
                //判断栈顶元素是否匹配
                char tmp = stack.peek();
                if (tmp == '(' && ch == ')' || tmp == '{' && ch == '}' || tmp == '[' && ch == ']') {
                    stack.pop();
                } else {
                    return false;
                }
            }
        }

        return stack.empty();
    }
}

3.3 逆波兰表达式求值

在这里插入图片描述

题目链接:逆波兰表达式求值
题目要求: 给定的字符串数组是逆波兰表达式,求逆波兰表达式的值
逆波兰表达式:(Reverse Polish Notation,RPN,或逆波兰记法),也叫后缀表达式(将运算符写在操作数之后),而中缀表达式就是我们平时看见的表达式,如何将中缀表达式转换为后缀表达式?分为两步
1.加括号:将表达式从左到右加括号(先乘除后加减)
2.移运算符:将括号内的运算符移到对应的括号外
在这里插入图片描述
解题思路: 要求逆波兰表达式的值,可以利用栈,申请一个栈,遍历字符串数组,如果是数字,则入栈,如果是操作符,出栈两个元素进行运算,先出栈的作为右操作数,后出栈的作为左操作数,将运算结果入栈。重复以上操作,当遍历完字符串数组时,此时栈内只剩下一个元素,该元素就是计算结果。
代码:

class Solution {
    public int evalRPN(String[] tokens) {
        Stack<Integer> stack = new Stack<>();
        for (int i = 0; i < tokens.length; i++) {
            String tmp = tokens[i];
            if (!isOperation(tmp)) {
                //如果不是操作符        
                Integer val = Integer.valueOf(tmp);//将字符转换为整型数字
                stack.push(val);
            } else {
                Integer val2 = stack.pop();
                Integer val1 = stack.pop();
                    switch (tmp) {
                    case "+":
                        stack.push(val1 + val2);
                        break;
                    case "-":
                        stack.push(val1 - val2);
                        break;
                    case "*":
                        stack.push(val1 * val2);
                        break;
                    case "/":
                        stack.push(val1 / val2);
                        break;
                }
            }
        }
        return stack.pop();
    }

    // 判断是否为操作符
    public boolean isOperation(String s) {
        if (s.equals("+") || s.equals("-") || s.equals("*") || s.equals("/")) {
            return true;
        }
        return false;
    }
}

3.4 出栈入栈次序匹配

在这里插入图片描述

题目链接: 出入栈次序匹配
题目要求: 给定pushV数组,表示入栈的顺序,判断popV数组是否可能为出栈的顺序
解题思路: 申请一个栈,遍历pushV数组,同时定义下标j用于遍历popV数组,依次将pushV的元素入栈,每入栈一个元素,判断该元素是否与popV的元素相等,如果相等,弹出栈顶元素,j++,否则pushV继续入栈,如果popV的元素一直与栈顶元素相等,则一直出栈,当遍历完pushV数组后,栈此时为空说明次序匹配,如果不为空说明不匹配。

代码:

    public boolean IsPopOrder(int[] pushV, int[] popV) {
        // write code here
        Stack<Integer> stack = new Stack<>();
        int j = 0;//遍历popv
        for (int i = 0; i < pushV.length; i++) {
            stack.push(pushV[i]);//先入栈,再判断
            while (j < popV.length && !stack.empty() && popV[j] == stack.peek()) {
                //j不能越界,并且栈不为空
                stack.pop();
                j++;
            }
        }
        return stack.empty();//判断最后的栈是不是空
    }

3.4 最小栈

在这里插入图片描述
题目链接: 最小栈
题目要求: 设计一个支持插入(push)、删除(pop)、获取栈顶元素(top)、getMin获取栈中最小元素,getMin的时间复杂度为O(1)
解题思路: 创建两个栈,一个为普通的栈,另一个为最小栈,最小栈的栈顶元素既为普通栈的最小值。入栈: 普通栈正常入栈,最小栈需判断入栈的值是否比最小栈的栈顶元素小,如果小于或者等于则入栈(如果最小栈为空则直接入栈)。出栈: 判断普通栈出栈的元素是否与最小栈的栈顶元素相等,如果相等最小栈也要出栈
代码:

class MinStack {

    public Stack<Integer> stack;
    public Stack<Integer> Min;

    public MinStack() {
        stack = new Stack<>();
        Min = new Stack<>();
    }

    public void push(int val) {
        stack.push(val);
        if (Min.empty() || val <= Min.peek()) {
            Min.push(val);
        }
    }

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

    public int top() {
        if (stack.empty()) {
            return -1;
        }
        return stack.peek();
    }

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

**今天的内容就到这里,感谢老铁们的点赞、收藏、评论~❤ **

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

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

相关文章

蓝桥杯嵌入式学习笔记(7):ADC程序设计

目录 前言 1. ADC原理 1.1 主要特性 1.2 模拟输出电路图 2. 使用CubeMX进行源工程的配置 2.1 引脚配置 2.2 配置AD1 2.3 配置AD2 2.4 配置时钟 3. 代码编程 3.1 预备工作 3.2 bsp_adc.h文件编写 3.3 bsp_adc.c文件编写 3.4 main.c编写 3.4.1 时钟函数配置 3…

内网渗透学习-漏洞利用

1、漏洞搜索与利用 漏洞1&#xff1a;后台弱口令 漏洞2&#xff1a; 在yxcms有个留言功能&#xff0c;常常存在存储型xss漏洞 先用<h1>123xss</h1>测试一下会不会解析 登录管理员账号审核留言&#xff0c;发现xss脚本解析了 写入xss弹窗 再次返回管理员审核页面&…

Hive on Spark 配置

目录 1 Hive 引擎简介2 Hive on Spark 配置2.1 在 Hive 所在节点部署 Spark2.2 在hive中创建spark配置文件2.3 向 HDFS上传Spark纯净版 jar 包2.4 修改hive-site.xml文件2.5 Hive on Spark测试2.6 报错 1 Hive 引擎简介 Hive引擎包括&#xff1a;MR&#xff08;默认&#xff09…

leaflet知识点:leaflet.draw的使用指南

一&#xff0c;安装插件 npm i leaflet-draw --save 二&#xff0c;引入插件 import "leaflet-draw"; import "leaflet-draw/dist/leaflet.draw.css";三&#xff0c;使用插件 leaflet-draw的插件使用有两种方法。 1. 作为工具栏控件加入到地图种使用 //…

linux离线安装NodeJs

一、官方下载 地址&#xff1a;Node.js — Download Node.js 选择linux系统版本 为了防止安装过程出现一些适配问题&#xff0c;我没有选择下载最新版&#xff0c;实际应该下载你的前端所用的nodejs版本 未完待续。。

深度解析Android APP加固中的必备手段——代码混淆技术

Android APP 加固是优化 APK 安全性的一种方法&#xff0c;常见的加固方式有混淆代码、加壳、数据加密、动态加载等。下面介绍一下 Android APP 加固的具体实现方式。 混淆代码 使用 ipaguard工具可以对代码进行混淆&#xff0c;使得反编译出来的代码很难阅读和理解&#xff…

3.5网安学习第三阶段第五周回顾(个人学习记录使用)

本周重点 ①SSRF服务器端请求伪造 ②序列化和反序列化 ③Vaudit代码审计 本周主要内容 ①SSRF服务器端请求伪造 一、概述 SSRF: server site request forgery (服务器端请求伪造)。 SSR: 服务端请求&#xff0c;A服务器通过函数向B服务器发送请求。 SSRF发生的前提条件…

idea 报错 Could not list the contents of folder “ftps

idea 报错 Could not list the contents of folder "ftps 解决方案 这里看到了网上的解决方案&#xff0c;顺便再记录一下。打开 【高级】菜单 - 取消勾选 被动模式。然后点击测试连接&#xff0c;显示连接成功&#xff01; ftp中的主动模式和被动模式 主动模式&…

1.JavaEE进阶篇 - 为什么要学习SpringBoot呢?

文章目录 1.为什么要学框架&#xff1f;2.框架的优点展示(SpringBoot VS Servlet)2.1 Servlet 项⽬开发2.1.1 创建项⽬2.1.2 添加引⽤2.1.3 添加业务代码2.1.4 运⾏项⽬(配置tomcat)2.1.5 Maven配置2.1.5.1修改本地Maven仓库地址2.1.5.2 配置settings.xml文件2.1.5.3项目 本地仓…

Nginx开发实战三:替换请求资源中的固定数据

文章目录 1.效果预览2.下载Nginx解压并初始化3.字符串替换模块安装4.修改nginx配置文件并重启 1.效果预览 页面初始效果 页面替换后效果 说明:页面是内网的一个地址&#xff0c;我们通过nginx可以很便捷的将其改为外网访问&#xff0c;但是在外网访问这个地址后&#xff0c…

剑指offer--数组中重复的数字

一.题目描述 在一个长度为 n 的数组 nums 里的所有数字都在 0&#xff5e;n-1 的范围内。数组中某些数字是重复的&#xff0c;但不知道有几个数字重复了&#xff0c;也不知道每个数字重复了几次。请找出数组中任意一个重复的数字。 算法1.排序,然后遍历,时间复杂度O(nlogn),空…

CVE-2023-4427:Out-of-bounds access in ReduceJSLoadPropertyWithEnumeratedKey

文章目录 前言环境搭建for-in && enum cache漏洞分析漏洞利用总结参考 前言 之前分析调试漏洞时&#xff0c;几乎都是对着别人的 poc/exp 调试&#xff0c;感觉对自己的提升不是很大&#xff0c;所以后面分析漏洞时尽可能全面分析&#xff0c;从漏洞产生原理、如何稳定…

前端学习<三>CSS进阶——0102-CSS布局样式

前言 css 进阶的主要内容如下。 1、css 非布局样式 html 元素的分类和特性 css 选择器 css 常见属性&#xff08;非布局样式&#xff09; 2、css 布局相关 css 布局属性和组合解析 常见布局方案 三栏布局案例 3、动画和效果 属于 css 中最出彩的内容。 多背景多投影特…

(C)1007 素数对猜想

1007 素数对猜想 问题描述 输入样例&#xff1a; 20 输出样例&#xff1a; 4 解决方案&#xff1a; #include<stdio.h> #include<string.h> #include<math.h> int main(){int n,d;int a[100000];int flag,jishu0;scanf("%d",&n);memset(a,-1,…

HubSpot出海CRM的优势有哪些?

强大的客户关系管理能力&#xff1a;HubSpot出海CRM提供了一套完整的客户关系管理功能&#xff0c;企业可以轻松地记录、整理和分析客户的各种信息&#xff0c;包括基本资料、购买历史、沟通记录等。这使得企业能够更深入地了解客户的需求和偏好&#xff0c;为后续的营销和销售…

持续交付/持续部署流水线介绍(CD)

目录 一、概述 二、典型操作流程 2.1 CI/CD典型操作流 2.2 CI/CD操作流程说明 2.3 总结 三、基于GitHubDocker的持续交付/持续部署流水线&#xff08;公有云&#xff09; 3.1 基于GitHubDocker的持续交付/持续部署操作流程示意图 3.2 GitHubDocker持续交付/持续部署流水…

2023.4.7 机器学习周报

目录 引言 Abstract 文献阅读 1、题目 2、引言 3、过去方案和Motivation 4、Segment Anything模型 5、创新点 6、实验过程 7、实验结果 1、评价绩效 2、检测评价 3、跟踪评价 8、 结论 总结 引言 本周阅读了一篇关于高效的任意分割模型的文献&#xff0c;用于自…

1区、TOP、CCF推荐,最快16天录用!4月刊源表已更新!

毕业推荐 SSCI • 社科类&#xff0c;分区稳步上升&#xff08;最快13天录用&#xff09; IEEE&#xff1a; • 计算机类&#xff0c;1区(TOP)&#xff0c;CCF推荐 SCIE • 计算机工程类&#xff0c;CCF推荐&#xff08;最快16天录用&#xff09; 2024年4月 SCI/SSCI/EI…

环境搭建 | Windows 11系统从0开始搭建SonarQube环境分析C sharp项目代码

1 安装&使用流程 JDK 17环境搭建Sonarqube 10.0安装PostgreSQL 12数据库安装配置MSBuild下载安装SonarScanner for MSBuild使用SonarQube分析C#代码并上传到服务器 注意&#xff1a;SonarQube环境搭建时对各个软件的版本都有要求&#xff0c;如果你不确定使用何版本&…

窥探未来:Web3如何颠覆传统互联网

随着科技的迅速发展&#xff0c;Web3正逐渐成为人们关注的焦点。与传统的Web2相比&#xff0c;Web3代表了一种全新的互联网模式&#xff0c;其潜力和影响力引发了人们对未来的期待和探索。本文将深入探讨Web3如何颠覆传统互联网的各个方面&#xff0c;并展望其可能带来的未来变…