数据结构——栈的实现(java实现)与相应的oj题
文章目录
- 一 栈
- 栈的概念:
- 栈的实现:
- 栈的数组实现
- 默认构造方法
- 压栈
- 获取栈元素的个数
- 出栈
- 获取栈顶元素
- 判断当前栈是否为空
- java提供的Stack类
- Stack实现的接口:
- LinkedList也可以当Stack使用
- 虚拟机栈,栈帧,栈的三个概念
- 二 栈的一些算法题:
- (1) 逆序打印单链表。
- (2)[括号匹配](https://leetcode-cn.com/problems/valid-parentheses)
- (3)[逆波兰表达式求值](https://leetcode-cn.com/problems/evaluate-reverse-polish-notation/)
- 逆波兰表达式
- (4) [出入栈次序匹配](https://www.nowcoder.com/practice/d77d11405cc7470d82554cb392585106?tpId=13&&tqId=11174&rp=1&ru=/activity/oj&qru=/ta/coding-interviews/question-ranking)
- (5)[最小栈](https://leetcode-cn.com/problems/min-stack/)
- 总结:
一 栈
栈的概念:
栈也是一种线性表,栈只允许在表的一端进行插入与删除操作,所以栈中数据的特征的先进后出(先进来的后出去)。
栈顶:是栈进行插入与删除操作的表的一端
栈底:不允许插入删除操作的一端
压栈:将数据插入到栈中
出栈:将数据移除栈
栈的实现:
栈的底层可以由数组实现,也可以由链表实现
栈由数组实现时,栈的压栈与出栈的时间复杂度均为O(1)。
栈由单链表实现时,
如果采用尾插法,压栈操作时间复杂度为O(n),如果有last指针,则
压栈时间复杂度为O(1),但是出栈的时间复杂度一定为O(n)。
如果采用头插法,则压栈与出栈的时间复杂度均为O(1).
栈由双链表实现时,不论采用头插法与尾插法,时间复杂度均为O(1)。
栈的数组实现
当栈使用数组实现时,栈的插入与删除操作,时间复杂度均为O(1);
public class MyStack {static int DEFAULT_SIZE = 10; //设置默认的数组大小private int [] element ; //实现栈的数组int usedsize = 0 ; //栈中有效元素的个数//默认构造方法public MyStack() {}//入栈public void push(int val) {}//出栈public int pop() {}//获取栈顶元素 但是不删除public int peek() { }//获取栈元素个数public int size(){} //判空public boolean isEmpty() { }
}
默认构造方法
默认申请10个空间
public MyStack(){this.element = new int[10];}
压栈
思想:先判断栈满没满,如果满了则扩容,然后进行压栈
public void push(int data){//先判断栈是否有空间if(usedsize==element.length){//如果没有空间//则扩容this.element = Arrays.copyOf(element,2*element.length);}//保证空间后this.element[usedsize++] = data;}
获取栈元素的个数
思想:直接返回usedsize
public int size(){return usedsize;}
出栈
思想:先判断栈是否为空,为空则抛出异常,不为空,则返回栈顶元素值,并且usedsize-1.
public int pop(){//要判断栈是否为空,如果为空,则退出try{if (isEmpty()) {//2. 问题出现,构造参数的形参问题,super()调用父类的构造方法throw new EmptyException("EmptyException异常报错");}}catch (EmptyException e){e.printStackTrace();}int val = this.element[usedsize-1];usedsize -- ;return val;}
获取栈顶元素
思想:与出栈逻辑相同,只是usedsize值不需-1 。
public int peek(){try{if (isEmpty()) {throw new EmptyException("EmptyException异常报错");}}catch (EmptyException e){e.printStackTrace();}return this.element[usedsize-1];}
判断当前栈是否为空
思想:直接判断usedsize 是否为0即可。
public boolean isEmpty(){return usedsize == 0;}
java提供的Stack类
Stack实现的接口:
接口说明 1. 继承Cloneable接口支持克隆其他接口,暂时还没搞明白,以后更新补充
LinkedList也可以当Stack使用
java提供的LinkedList类也可以当做栈来使用,LinkedList的方法列表如下:
public class Test {public static void main(String[] args) {LinkedList<Integer> stack = new LinkedList<>();stack.push(5);stack.push(2);stack.pop();stack.pop();stack.pop();}
}
虚拟机栈,栈帧,栈的三个概念
虚拟机栈是JVM中的一块内存。
栈帧是为一个方法,函数分配的内存。
栈是一种数据结构。
二 栈的一些算法题:
(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)括号匹配
题解:1 . 对于这个题无法直接看出其数学模型,必须先画图,列出各种情况,再判断
从图中可以分析出,要实现判断括号匹配
- 就要使得每一个左括号和右括号能够与对应位置的右括号进行匹配判断
- 且当所有的左括号(右括号)判断完时,其对应的右括号(左括号)也判断完毕,即满足左括号个数与右括号个数相当的情况。
- 如果第一个括号是右括号,说明此括号没有对应的左括号,说明一定为字符串一定括号不匹配。
实现思想:遍历字符串,遇到左括号则存入栈中,遇到右括号则与栈顶元素比较,相匹配,则继续循环,如果不匹配或栈为空,则返回false。
class Solution1 {public boolean isValid(String s) {Stack <Character> stack = new Stack<>();//采用for循环,这样可以找到字符串中的字符for(int i =0;i<s.length();i++) {char ch = s.charAt(i);if (ch == '{' || ch == '[' || ch == '(') {//问题,java提供的栈是否需要手动扩容?stack.push(ch);} else {//如果是右括号的内容if (stack.isEmpty()) {return false;} else {char ch2 = stack.peek(); //当获取栈顶元素时,栈可能为空//栈区不能为空if (((ch == '}' && ch2 == '{') || (ch == ']' && ch2 == '[') || (ch == ')' && ch2 == '('))) {//说明匹配,//将栈顶的元素去除stack.pop();} else {//如果不匹配,情况1 如果栈中还没有左括号,则一定不匹配,return false;}}}}// 如果栈表为空,说明匹配完毕if(stack.isEmpty()){return true;}return false;}
}
(3)逆波兰表达式求值
逆波兰表达式
逆波兰表达式即后缀表达式,后缀表达式是由中缀表达式转换而成。
所谓中缀表达式即我们平常所写的±*/的算式
我们平常所写的中缀表达式中是有优先级的,即先乘除,后加减,有括号先算括号里面的
但是计算机是不能够识别优先级的,为了能够使计算机计算,我们将中缀表达式的规则
表达成后缀表达式的形式,这样计算机便能够计算算式。
中缀表达式转换成后缀表达式的的规则:
- 先将中缀表达式中能够加括号的部分都加上括号
- 然后将所有的运算符移到所在 最近扩号之外。
- 然后去除掉所有括号即得到后缀表达式。
后缀表达式的运算规则:
遍历整个表达式,遇到运算符时,则将运算符前面的两个数作为操作数计算
得出的结果替代两个操作数,然后继续遍历表达式,循环上次操作。
本题:只是要求按照后缀表达式的规则计算结果
实现思想:遍历表达式,遇到操作数即将操作数压入栈中,遇到运算符,则进行两次出栈
,获取两个操作数进行计算(需要注意的是第一次出栈的是右操作数,第二次出栈的是左操作数)
然后将计算的结果再进行压栈,然后循环此操作。
class Solution {public int evalRPN(String[] tokens) {//创建一个栈,创建栈时不需要考虑栈的空间大小Stack<Integer> stack = new Stack<>();//采用foreach进行遍历栈for (String str : tokens) {if (!isOperator(str)) {int a = Integer.parseInt(str);stack.push(a);} else {int val2 = stack.pop();int val1 = stack.pop();//如果为运算符switch (str) {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.peek();}
总结
1. 字符串形式的运算符不能直接转换成运算符
2. 后缀表达式先进栈的是左操作数,后进栈的是右操作数,当我们需要出栈时,第一次获取栈顶元素是右操作数,第二次获取栈顶元素才是左操作数。
(4) 出入栈次序匹配
class Solution2{public boolean IsPopOrder (int[] pushV, int[] popV) {// write code hereStack<Integer> stack = new Stack<>();int j = 0;for(int i = 0; i< pushV.length;i++) {stack.push(pushV[i]);while(!stack.empty() && j < popV.length &&stack.peek() == popV[j]) {stack.pop();j++;}}return stack.empty();}
}
(5)最小栈
题解:
如果只用一个栈的话,我们不可能实现题目的要求,只有能将栈的最小值时刻储存起来才能实现题目的要求。因此我们实现两个栈,一个栈用于存储数据,另一个最小栈用于存放栈当前的最小值。
实现思想:入栈的规则:
- 普通栈一定要放,最小栈如果为空,或者栈顶元素小于压入的数据,则放入最小栈中
- 如果压入的数据与最小栈栈顶元素相当,也放入最小栈中。(因为最小栈中的元素必须与普通栈的最小值保持同步即必须与出栈的规则相匹配)。
出栈的规则:
如果普通栈的栈顶元素与最小栈栈顶元素相同,则最小栈也需要出栈。
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() {//出栈//普通栈一定出栈int val = stack.pop();//最小栈出栈://如果两栈的栈顶元素相同,则出栈if(val == minStack.peek()){minStack.pop();}}public int top() {//获取栈顶元素if(!stack.empty()){return stack.peek();}return -1 ;}public int getMin() {if(minStack.empty()){return -1;}return minStack.peek();}}
总结:
在使用栈时,最常用的运用是根据栈先进后出的特性,将一段有序的数据转为逆序后,再进行操作使用。
相关文章:
数据结构——栈的实现(java实现)与相应的oj题
文章目录 一 栈栈的概念:栈的实现:栈的数组实现默认构造方法压栈获取栈元素的个数出栈获取栈顶元素判断当前栈是否为空 java提供的Stack类Stack实现的接口: LinkedList也可以当Stack使用虚拟机栈,栈帧,栈的三个概念 二 栈的一些算…...
linux修改时区为CST
目录 第一步: 第二步: 第三步: 第一步: 备份原来的时区信息 [rootlocalhost ~]# mv /etc/localtime localtime.bak 第二步: 通过软链接将亚洲/上海 的时区信息 指导时区信息 [rootlocalhost ~]# ln -s /usr/share…...
【Spring Security】初识Spring Security
今天晚上因为一个项目问题,而正式开始学习Spring Security。 这个问题是“APP端的操作员应仅可查看管理后台的项目负责人分配给自己的计划”。 一、Spring Security的核心组件: Spring Security的核心组件包括:SecurityContextHolder、Auth…...
配置单区域OSPF
目录 引言 一、搭建基础网络 1.1 配置网络拓扑图如下 1.2 IP地址表 二、测试每个网段都能单独连通 2.1 PC0 ping通Router1所有接口 2.2 PC1 ping通Router1所有接口 2.3 PC2 ping通Router2所有接口 2.4 PC3 ping通Router2所有接口 2.5 PC4 ping通Router3所有接口 2.…...
SQL中的游标是什么?
在 SQL 中,游标(Cursor)是一种用于遍历结果集的数据库对象。它允许开发者在 SQL 查询的结果集中逐行或逐批处理数据。 具体来说,SQL 中的游标通常用于以下目的: 遍历结果集:当一个 SQL 查询返回多行结果时…...
7. LangChain4j如何使用统一api调用?
前言 当我们对接LangChain4j的时候,面对复杂的各种各样的大模型的api的对接,让很多开发者感到力不从心。在每个大模型的api都不一样的时候?该如何快捷的切换模型的使用呢? 这时,One-API应运而生,它以其简洁…...
RPM、YUM 安装 xtrabackup 8 (mysql 热备系列一)包含rpm安装 mysql 8 配置主从
RPM安装 percona-xtrabackup-80-8.0.35-30.1.el7.x86_64.rpm 官网: https://www.percona.com/ 下载地址: https://www.percona.com/downloads wget https://downloads.percona.com/downloads/percona-distribution-mysql-ps/percona-distribution-mysq…...
maven项目打成可运行的jar及pom中的依赖一同打包
maven项目打jar及pom中的依赖一同打包 最近开发中有个需求,不部署新的服务,只jar包执行 那maven项目中,代码如何以jar的方式运行、如何把代码打成jar、pom中的依赖如何与代码一同打到jar包中? 1、代码如何以jar的方式运行&…...
Gettler‘s Screep World 笔记 Ⅰ
夏促时候刚刚入坑,写个笔记叭~ 环境配置 参考 HoPGoldy 大佬的简书,先配置下开发环境 萌新去看大佬的详细教程,我这里比较简单,有前端基础的可以直接抄 VSCode 跳过 node 我配的是v18.18.2 换源 npm config set registry h…...
联合体(union)的定义以及如何与结构体(struct)不同
联合体(Union)是一种特殊的数据类型,它允许在相同的内存位置存储不同的数据类型。但是,在任何给定的时间点,联合体只能存储其中的一个值;这意味着联合体的大小是其最大成员的大小,因为它必须足够…...
【Spark官方文档部分翻译】RDD编程指南(RDD Programming Guide)
写在前面 内容如何选择 本翻译只翻译本人认为精华的部分,本人认为的Spark的一些核心理念,编程思想。一些特别基础的操作包括但不限于搭建环境就不在此赘述了。 配套版本 本系列基于Spark 3.3.1,Scala 2.12.10,进行翻译总结 原…...
前端八股文 $set
为什么会有$set vue2中对数组中新增的属性是监听不到的 如图 vue 插件中有但是 视图中没有刷新 解决方法 解决就是 $set() 就是在数组中新增属性的时候可以重新渲染视图 具体的写法 写法 就是 第一个 是在那个对象上新增 第二个参数 是新增的属性 第三个参数是 新增的属性…...
Connecting weaviate with langflow across docker containers
题意:在Docker容器之间连接Weaviate与Langflow 问题背景: I am trying to build a local RAG application using Langflow. For my vectore store, I want to use a local Weaviate instance, hosted in a separate docker container on the same netwo…...
【linux vim使用说明】
基本概念 提示:本文是网络资源整理 模式: vim 有多种模式,每种模式都有不同的功能。 普通模式 (Normal Mode): 默认模式,用于导航和执行命令。插入模式 (Insert Mode): 用于文本输入。可以通过按 i 进入。可视模式 (Visual Mode): 用于选择…...
cocos2d-x安装和项目
首先多方查找资料发现教程很简洁,发现对自己的操作方面没多大帮助,后来干脆去官网,好像也很简洁。基于这样一个原因,加上我首次碰cocos2d-x,决定记录一下整个流程,解决实际操作上的疑惑。 涉及的方面&…...
因果推断 | 双重机器学习(DML)算法原理和实例应用
文章目录 1 引言2 DML算法原理2.1 问题阐述2.2 DML算法 3 DML代码实现3.1 策略变量为0/1变量3.2 策略变量为连续变量 4 总结5 相关阅读 1 引言 小伙伴们,好久不见呀。 距离上次更新已经过去了一个半月,上次发文章时还信誓旦旦地表达自己后续目标是3周更…...
Flutter 开源库学习
网上看了好多歌词实现逻辑相关资料,封装比较的好的 就 flutter_lyric,核心类是LyricsReader,而且如果实现逐字逐句歌词编辑功能还需要自己实现很多细节 ,网友原话是 :歌词的功能真的是不少,写起来也是挺难的…...
自主巡航,目标射击
中国机器人及人工智能大赛 参赛经验: 自主巡航赛道 【机器人和人工智能——自主巡航赛项】动手实践篇-CSDN博客 主要逻辑代码 #!/usr/bin/env python #coding: utf-8import rospy from geometry_msgs.msg import Point import threading import actionlib impor…...
MySQL中EXPLAIN关键字详解
昨天领导突然问到,MySQL中explain获取到的type字段中index和ref的区别是什么。 这两种状态都是在使用索引后产生的,但具体区别却了解不多,只知道ref相比于index效率更高。 因此,本文较为详细地记录了MySQL性能中返回字段的含义、状…...
如何理解ref toRef和toRefs
是什么 ref 生成值类型的响应式数据可用于模板和reactive通过.value修改值 ref也可以像vue2中的ref那样使用 toRef 针对一个响应式对象(reactive)的prop创建一个ref两者保持引用关系 toRefs 将响应式对象(reactive封装)转换…...
【linux】kernel-trace
文章目录 linux kernel trace配置trace内核配置trace接口使用通用配置Events配置Function配置Function graph配置Stack trace设置 跟踪器tracer功能描述 使用示例1.irqsoff2.preemptoff3.preemptirqsoff linux kernel trace 配置 源码路径: kernel/trace trace内…...
【Golang 面试基础题】每日 5 题(一)
✍个人博客:Pandaconda-CSDN博客 📣专栏地址:http://t.csdnimg.cn/UWz06 📚专栏简介:在这个专栏中,我将会分享 Golang 面试中常见的面试题给大家~ ❤️如果有收获的话,欢迎点赞👍收藏…...
ETCD介绍以及Go语言中使用ETCD详解
ETCD介绍以及Go语言中使用ETCD详解 什么是etcd ETCD是一个分布式、可靠的key-value存储的分布式系统,用于存储分布式系统中的关键数据;当然,它不仅仅用于存储,还提供配置共享及服务发现;基于Go语言实现 。 etcd的特点 完全复制:集群中的每个节点都可以使用完整的存档高…...
03-用户画像+Elasticsearch
优点 es支持海量数据的写入和更新es可以和hadoop,hive及spark进行集成es支持hivesql的操作,可以通过hivesql将数据导入eses的在进行数据检索查询是速度比较快es是分布式存储 应用 全文检索 全文检索流程: 1-对文档数据(文本数据)进行分词 2-将分词…...
初学Mybatis之搭建项目环境
在连接 mysql 数据库时,遇到了个 bug,之前都能连上,但报错说换了个 OS 操作系统什么的 然后搜索怎么连接,找到了解决方法 MySQL MYSQL – 无法连接到本地MYSQL服务器 (10061)|极客教程 (geek-docs.com) 命令行输入 services.msc…...
JMeter使用小功能-(持续更新)
1、jmeter在同一个线程组内,uuid的复用 方式一: 方式二: 2、获得jMeter使用的线程总数 ctx.getThreadGroup().getNumberOfThreads()来表示活动线程总数 int threadNumctx.getThreadGroup().getNumThreads(); String threads Integer…...
科研绘图系列:R语言火山图(volcano plot)
介绍 火山图(Volcano Plot),也称为火山图分析,是一种在生物信息学和基因组学中常用的图形表示方法,主要用于展示基因表达数据的差异。它通常用于基因表达微阵列或RNA测序数据的可视化,帮助研究人员识别在不同条件下表达差异显著的基因。 火山图的基本构成 X轴:通常表示…...
docker firewalld 防火墙设置
1、环境 centos 7 firewalld docker-ce docker 默认会更改防护墙配置 导致添加的防火墙策略不生效,可以启用firewalld 重新设置策略 2、启用防火墙 systemctl start firewalld systemctl enable firewalld3、配置文件禁用docker 的iptables /etc/docker/daemon.js…...
《问题004:报错-JS问题-unknown: Invalid shorthand property initializer.》
问题描述: unknown: Invalid shorthand property initializer. (25:13) unknown:无效的简写属性初始化项 解决方法: “”应该写为“:”(globalData 改成 globalData: )...
什么是 MLPerf?
什么是 MLPerf? MLPerf 是一个用于衡量机器学习硬件、软件和服务性能的标准化基准测试平台。它由 MLCommons 组织开发,该组织是由多家领先的科技公司和学术机构组成的。MLPerf 的目标是通过一系列标准化的基准测试任务和数据集,提供一个统一…...
大航母网站建设与服务/百度联盟广告点击一次收益
一、 集群概述 1、 什么是集群? 一组各自相互独立且又相互依赖的,通过高速网络互联的计算机组成的一个计算机组, 以单一的系统模式加以管理, 为用户提供服务, 对用户来说, 用户只会认为对方是一个服务. 这个里面, 一组计算机的一台计算机就是集群的一个节点 2、 集…...
门户网站建设与推广方案/汽车营销活动策划方案
本质上,这很可能是坏块引发的,所以需要调查 关联的Table 中的坏块状况: Excerpt of trace file *** 2017-08-18 09: 23: 04.323 dbkedDefDump (): Starting incident default dumps (flags 0x2, level 3, mask 0x0) [TOC00009] ----- Cur…...
软件开发包含网站开发/网站域名费一年多少钱
SPI全名Service Provider Interface(服务提供者接口),SPI的主要目的是实现服务的热插拔效果,主要应对的场景是设计者提供一个接口,这个接口的具体实现由不同厂商提供,设计者只要引入厂商提供的实现jar包就可…...
湘潭县建设投资有限公司网站/seo搜索引擎优化介绍
╮(╯▽╰)╭,又是一年惆怅时。 周围同事也下班啦,一个个的说“来年见”;办公司就剩下我自己,在博客园记录这一年的点点滴滴。 这一年,感觉挺失败的。 年初的时候,24年里,唯一的一次恋爱也早早流…...
wordpress swf 上传/惠州seo排名收费
什么是存储过程:存储过程一般用于处理比较复杂的任务,基础ms这个平台,可以大大降低耗时,其编译机制也提高了数据库执行速度。 当然在系统控制方便方面,例如当系统进行调整时,这是只需要将后台存储过程进行更…...
医药企业网站建设/秒收录关键词代发
C语言中内存的管理主要是依据malloc和free实现的,其中malloc主要是实现内存的分配,而free则是实现内存的释放。虽然这是我们已经很熟悉的,但是还是存在一些问题。特别是当结构体中存在指针的情况下,各种问题也就会展现出来。 其中…...