[Java]栈--Stack

news2024/12/26 0:35:08

前言

熟悉Class Stack.

关于栈—笔者的C语言描述
java.util包有Stack集合类.
JDK17的Stack源码非常简单,能相对轻易看懂.
我们能用Stack类来充当栈,Java框架中LinkedList(双向链表)实现了双端队列(Deque),也能当作栈使用.
Stack类是基于数组实现.

public Stack<E> extends Vector<E>{
	...
}
Stack() 构造一个空的栈
E push(E e) 将e入栈,并返回e
E pop() 将栈顶元素出栈并返回
E peek() 获取栈顶元素
int size() 获取栈中有效元素个数
boolean empty() 检测栈是否为空

Stack类里面提供了6种常用方法,JDK17中Stack类里面只有这6种方法.
Stack可以调用父类Vector的方法,若只是当作栈使用,这6种方法足够了.
入栈:对应push
出栈:对应pop,同时可以获取堆顶元素.
获取堆顶元素:对应peek

栈使用实例

用栈倒序打印链表元素.

   public static void main(String[] args) {
        LinkedList<Integer> list = new LinkedList<>();
        list.add(1);
        list.add(2);
        list.add(3);
        list.add(4);
        list.add(5);
        var stack = new Stack<Integer>();
        for(int x:list) {
            stack.push(x);
        }
        while(!stack.isEmpty())
        {
            System.out.println(stack.pop()+" ");
        }
    }

有效的括号

在这里插入图片描述

多看几组数据
s = "()"—true
s = "()[]{}"—true
s = "(]"—false
s = ([)]—false
为什么想到用栈这一数据结构呢?
栈的特点是后进先出.左括号与右括号的匹配是什么样的模式?
显而易见,右括号会与它最近的左括号匹配—若匹配失败则一定不是.
最近一词,显然满足后进先出的特点,与栈不谋而合.
算法设计:

  1. 遍历字符串,若遇到左括号进行入栈处理.
  2. 若遇到右括号则进行匹配,过程就是将最近的左括号出栈匹配.
  3. 匹配失败则结束循环,否则继续按照1,2过程遍历.
  4. 字符串遍历结束.检查栈是否为空.
  5. 栈不为空,说明左括号和右括号一定不等,返回false.
    另外,字符串长度必须为偶数,才有可能满足上述条件.
class Solution {
    public boolean isValid(String s) {
        if(s.length()%2==1)
            return false;
        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.isEmpty())
                    return false;
                char c2 = stack.peek();
                if((c2=='('&&c ==')')
                 ||(c2=='['&&c==']')
                 ||(c2=='{'&&c=='}'))
                    stack.pop();
                else
                    return false;
            }
        }
        if(!stack.isEmpty())
            return false;
        return true;
    }
}

用栈实现队列

在这里插入图片描述

class MyQueue {

    public MyQueue() {

    }
    
    public void push(int x) {

    }
    
    public int pop() {

    }
    
    public int peek() {

    }
    
    public boolean empty() {

    }
}

偷偷用双端队列秒了这道题

class MyQueue {
    Deque<Integer> stack;
    public MyQueue() {
        stack = new LinkedList<Integer>();
    }
    
    public void push(int x) {
        stack.addLast(x);
    }
    
    public int pop() {
        if(stack.isEmpty())
            return Integer.MAX_VALUE;
        return stack.pollFirst();
    }
    
    public int peek() {
         if(stack.isEmpty())
            return Integer.MAX_VALUE;
        return stack.peekFirst();
    }
    
    public boolean empty() {
        return stack.isEmpty();
    }
}

将栈改为队列的过程就是将后进先出改为先进先出
若只是用标准队列(题目要求),单个栈是做不到的.
这里采用双栈实现队列----这里用Stack类.
队列核心操作—入队出队.
为简化过程,我们将一个栈定义为输入栈inStack,另一个栈为输出栈outStack.

    Stack<Integer> inStack;
    Stack<Integer> outStack;
    public MyQueue() {
        inStack = new Stack<>();
        outStack  = new Stack<>();
    }

压栈的操作很简单:inStack进行入栈操作即可.

 public void push(int x) {
        inStack.push(x);
    }

出栈的操作那么交给outStack吧.
想象inStack的每个元素像各种颜色分层的水.只要将这杯水倒到outStack这个杯里.假设不考虑密度因素.那么原先杯底的元素现在在杯顶了.—只要将这个outStack这杯水倒掉,让其重新为空.原先进inStack的顺序和出outStack的顺序一样了,满足先进先出.
下面我们翻译成贴近伪代码的描述
算法思想:

  1. 如果outStack的元素不为空,就直接出栈,否则执行第二步.
  2. inStack的元素依次出栈并压入outStack直到前者为空栈.
  3. 输出outStack的元素.
    peek方法大同小异,其它方法自行观察代码很容易.如下:
class MyQueue {
    Stack<Integer> inStack;
    Stack<Integer> outStack;
    public MyQueue() {
        inStack = new Stack<>();
        outStack  = new Stack<>();
    }
    
    public void push(int x) {
        inStack.push(x);
    }
    
    public int pop() {
        if(empty())
            return Integer.MAX_VALUE;
        if(outStack.isEmpty())
        {
            while(!inStack.isEmpty())
            {
            outStack.push(inStack.pop());
            }
        }
        return outStack.pop();
    }
    
    public int peek() {
         if(empty())
            return Integer.MAX_VALUE;
         if(outStack.isEmpty())
        {
            while(!inStack.isEmpty())
            {
            outStack.push(inStack.pop());
            }
        }
        return outStack.peek();
    }
    
    public boolean empty() {
        return inStack.isEmpty()&&outStack.isEmpty();
    }
}

validate-stack-sequences

在这里插入图片描述
本题翻译一下:已知入队序列,验证popped数组是其出队序列的一种.
你可能有点困惑:
比如,已知1个栈的入栈序列为ABCDE,那么其可能的出队序列.
入栈序列不一定是其这个过程一直入栈而不出栈
假设其一直入栈,然后再依次出栈,那么出栈序列是EDCBA.
假设其入一个元素,出一个元素,那么出栈序列是ABCDE.入栈序列和出栈序列一样
那么有什么规律吗?
上面两种情况是不是极其特殊的情况?那么一般情况就是取自两者.
连续入栈的序列,对应出栈序列部分必然是对称的.
入一个出一个,对应出栈序列部分必然相同的.
算法思想:
模拟入栈出栈这一过程.
[1,2,3,4,5]---->[4,5,3,2,1]
找到入队序列与出队序列的第一个数匹配的位置.
此时栈上:[1,2,3,4]—匹配到了’4’,将4移除出去.
此时栈上:[1,2,3,5]—5入栈了,与5匹配.
接下来的3,2,1序列,正好对应出栈3,2,1.

//c语言传统---写数据结构了.
typedef struct{
    int *a;
    int top;
    int size;
}Stack;
Stack *newStack()
{
    Stack *stack = (Stack*)malloc(sizeof(Stack));
    stack->a = (Stack*)malloc(sizeof(int) * 10);
    stack->top=0;
    stack->size = 10;
    return stack;
}
void push(Stack *stack,int val)
{
    if(stack->top==stack->size)
    {
        stack->a=(int*)realloc(stack->a,sizeof(int)*2*stack->size);
        stack->size = 2 * stack->size;
    }
    stack->a[stack->top++]=val;
}
int pop(Stack *stack)
{
    return stack->a[--stack->top];
}
int peek(Stack *stack)
{
    return stack->a[stack->top-1];
}
bool isEmpty(Stack *stack)
{
    return stack->top==0;
}
bool validateStackSequences(int* pushed, int pushedSize, int* popped, int poppedSize) {
    Stack *stack = newStack();
    int j = 0;
    for(int i = 0;i<pushedSize;i++)
    {
        push(stack,pushed[i]);
        while(!isEmpty(stack)&&j<poppedSize&&peek(stack)==popped[j])
        {
            pop(stack);
            j++;
        }
    }
    return isEmpty(stack);
}
class Solution {
    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.isEmpty()&&j<popped.length&&stack.peek()==popped[j])
            {
                stack.pop();
                j++;
            }
       }
       return stack.isEmpty();
    }
}

Min Stack

最小栈问题.
在这里插入图片描述[-1,0,2,0,-3,-2]:这样的一个入栈序列.
构建一个辅助栈,来存储最小值.

	 private Stack<Integer>stack;
     private Stack<Integer>minStack;
     //构造器
        public MinStack() {
        stack = new Stack<>();
        minStack = new Stack<>();
    }

首先,如上分出一个普通栈与最小栈.
逻辑:普通栈与最小栈要么都为空栈,要么都非空.----这个逻辑很简单.
只要普通栈存在数,那么必定有最小值,最小栈就不能为空栈.
现在模拟这个序列入栈:
当-1入普通栈时,最小栈为空,-1是最小值.
当0入普通栈,最小栈非空,由于-1<0.0不是这个序列最小值,不如最小栈.
当2入栈同理.
当第二个0入栈时,由于0=0,此时0也要入最小栈.
当-3入普通栈时,-3小于最小栈堆顶0,也要入最小栈.

普通栈:[-1,0,2,0,-3,-2]
最小栈:[-1,0,0,-3]
可以发现最小栈就是存储的普通栈子序列的极小值,只要对于全序列,最小栈的堆顶元素才是真正意义的最小值.

模拟入栈:
1. 普通栈一定入栈;最小栈入栈有两种情况:1.空栈必须入栈,2.入栈元素<=当前堆顶元素.

public void push(int val) {
        stack.push(val);
        if(minStack.isEmpty())
            minStack.push(val);
        else if(val<=minStack.peek())
            minStack.push(val);
        else
            return ;

    }

模拟出栈
1. 若栈为空,返回一个无效值:比如Integer.MAX_VALUE
2. 普通栈一定出栈.
3.最小栈出栈判定:若普通栈出栈元素等于最小栈堆顶元素,说明当前序列最小值出去了,那么最小栈也要出栈.

   public void pop() {
        if(stack.isEmpty())
            return ;
        int popVal = stack.pop();
        if(popVal==minStack.peek())
        {
            minStack.pop();
        }
    }

获取堆顶元素:正常获取直接返回普通栈的堆顶元素

   public int top() {
        if(stack.empty()){
            return Integer.MAX_VALUE;
        }
        return stack.peek();
    }

获取最小值:最小栈堆顶元素即是当前栈序列的最小值,返回最小栈堆顶元素即可.

public int getMin() {
        if(minStack.empty())
            return Integer.MAX_VALUE;
        return minStack.peek();    
    }

Java解法

class MinStack {
    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.isEmpty())
            minStack.push(val);
        else if(val<=minStack.peek())
            minStack.push(val);
        else
            return ;

    }
    
    public void pop() {
        if(stack.isEmpty())
            return ;
        int popVal = stack.pop();
        if(popVal==minStack.peek())
        {
            minStack.pop();
        }
    }
    
    public int top() {
        if(stack.empty()){
            return Integer.MAX_VALUE;
        }
        return stack.peek();
    }
    
    public int getMin() {
        if(minStack.empty())
            return Integer.MAX_VALUE;
        return minStack.peek();    
    }
}

这么一来,做了这些题,你大致就能玩熟Stack了吧.
Deque实现类LinkedList也能充当栈使用.
好久没更了,水一篇(^ - ^).

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

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

相关文章

腾讯云AI代码助手:AI辅助编写测试用例,测试从此不求人

目录 引言 开发环境介绍 实例&#xff1a;编写测试用例 帮助与提升 建议 结语 引言 在软件开发过程中&#xff0c;编写测试用例是确保代码质量的重要环节。然而&#xff0c;对于新手编程学习者来说&#xff0c;撰写高质量的测试用例可能是一个巨大的挑战。AI 代码助手作为一个智…

基于Android aosp系统的云手机chromium浏览器定制

chromium定制浏览器 chromium源码下载get属性c或者c层常见指纹检测指标 chromium源码下载 最新有点时间研究了一些 网上定制chromium 浏览器的方案&#xff0c;大部分都是基于window的&#xff0c; 修改点无非以下监测点。自己本身做Android系统开发&#xff0c;就想着能否做一…

【AI大模型】Langchain探秘之旅:深入Prompt世界,解锁多种PromptTemplate的实战奇技!

文章目录 前言一、Langchain 概述1. 概述2. 应用场景3. 案例 二、Prompt1.Prompt 介绍2.PromptTemplatea.PromptTemplate 案例单个参数多个参数多个参数-结合字典解包 b.使用jinja2与f-string来实现提示词模板格式化 3.ChatPromptTemplatea.ChatPromptTemplate 介绍b.ChatPromp…

2024年8月一区SCI-海市蜃楼优化算法Fata morgana algorithm-附Matlab免费代码

引言 本期介绍了一种基于地球物理的高效优化方法名为海市蜃楼优化算法Fata morgana algorithm&#xff0c;FATA的元启发式算法。通过模拟海市蜃楼的形成过程&#xff0c;FATA分别设计了海市蜃楼滤光原理(MLF)和光传播策略(LPS)。该成果于2024年8月最新上线在JCR 1区&#xff0…

C#重要知识归纳总结

C#教程 C# 结构体&#xff08;Struct&#xff09; | 菜鸟教程C# 结构体&#xff08;Struct&#xff09; 在 C# 中&#xff0c;结构体&#xff08;struct&#xff09;是一种值类型&#xff08;value type&#xff09;&#xff0c;用于组织和存储相关数据。 在 C# 中&#xff0c…

学习c语言第二十二天(c语言文件操作)

1. 为什么使用文件&#xff1f; 我们前面学习结构体时&#xff0c;写了通讯录的程序&#xff0c;当通讯录运行起来的时候&#xff0c;可以给通讯录中增加、删除数据&#xff0c;此时数据是存放在内存中&#xff0c;当程序退出的时候&#xff0c;通讯录中的数据自然就不存在了&…

工地人员定位系统的功能和作用

工地人员定位系统是一种基于实时定位技术的管理系统&#xff0c;旨在为施工单位提供安全、高效的管理服务。该系统可以对工人进行实时监控与管理&#xff0c;极大地提高了工地施工安全性和工作效率&#xff0c;降低了工伤事故频率。通过使用该系统&#xff0c;施工单位能够实时…

解决mqtt在线或离线监听问题的多种方法

目录 前言 优缺点&#xff1a; 1.创建 DeviceMqttCallBacked类&#xff0c;实现 MqttCallbackExtended 接口&#xff0c;添加带cleintId参数的构造方法。 2. 在Mqtt连接成功之后&#xff0c;设置回调类。 3.执行上述代码&#xff0c;查看emqx界面 4.从emqx上踢除设备 5…

html+css 实现hover酷炫发光按钮

前言&#xff1a;哈喽&#xff0c;大家好&#xff0c;今天给大家分享htmlcss 绚丽效果&#xff01;并提供具体代码帮助大家深入理解&#xff0c;彻底掌握&#xff01;创作不易&#xff0c;如果能帮助到大家或者给大家一些灵感和启发&#xff0c;欢迎收藏关注哦 &#x1f495; 文…

“5G+Windows”推动全场景数字化升级:美格智能5G智能模组SRM930成功运行Windows 11系统

操作系统作为连接用户与数字世界的桥梁&#xff0c;在数字化迅速发展的时代扮演着至关重要的角色&#xff0c;智能设备与操作系统的协同工作&#xff0c;成为推动现代生活和商业效率的关键力量。其中&#xff0c;Windows系统以其广泛的应用基础和强大的兼容性成为全球最广泛使用…

服务器启动jar包的时候报”no main manifest attribute“异常(快捷解决)

所以,哥们,又出现问题咯.没事,我也出现了,哈哈哈哈哈,csdn感觉太麻烦了,所以搞了一篇这个. 没得事,往下看,包解决的. 希望可以帮助到各位&#xff0c;感谢阅览&#xff01; 小手点个赞&#xff0c;作者会乐烂哈哈哈哈哈哈&#x1f606;&#x1f606;&#x1f606;&#x1f606…

Linux中多线程压缩软件 | Mingz

原文链接&#xff1a;Linux中多线程压缩软件 本期教程 软件网址&#xff1a; https://github.com/hewm2008/MingZ安装&#xff1a; git clone https://github.com/hewm2008/MingZ.git cd MingZ make cd bin ./mingz -h使用源码安装&#xff1a; 若是你的git无法使用安装&am…

【IEEE出版 | 高校主办】第三届人工智能、物联网和云计算技术国际会议(AIoTC 2024)

第三届人工智能、物联网和云计算技术国际会议&#xff08;AIoTC 2024&#xff09; 2024 3rd International Conference on Artificial Intelligence, Internet of Things and Cloud Computing Technology 2024年9月13-15日 | 中国武汉 重要信息 大会官网&#xff1a;www.ic…

Jboss 漏洞

一.CVE-2015-7501 访问/invoker/JMXInvokerServlet 开启下载存在漏洞 二.CVE-2017-7504 三CVE-2017-12149 启动vulhub环境&#xff0c;访问/invoker/readonly出现如下界面&#xff0c;说明存在漏洞 使用工具连接 四.Administration Console弱⼝令 访问/admin-console/login…

高职物联网智慧农业实训室建设方案

一、项目概述 随着物联网技术的迅猛发展及其在农业领域的广泛应用&#xff0c;智慧农业已经成为推动农业现代化的关键力量。近年来&#xff0c;国家高度重视物联网技术在农业领域的应用与发展&#xff0c;出台了一系列相关政策支持智慧农业建设。如《数字乡村发展战略纲要》明…

Dubbo框架实现RPC远程调用

项目背景介绍 这个技术我是直接在项目中运用并且学习的&#xff0c;所以我写笔记最优先的角度就是从项目背景出发 继上一次API网关完成了这个实现用户调用一次接口之后让接口次数增多的操作之后&#xff0c;又迎来了新的问题。 就是我们在调用接口的时候需要对用户进行校验&…

苍穹外卖day12(day15)---数据统计——Excel报表(项目完结)

工作台 接口设计 新建admin/WorkSpaceController /*** 工作台*/ RestController RequestMapping("/admin/workspace") Slf4j Api(tags "工作台相关接口") public class WorkSpaceController {Autowiredprivate WorkspaceService workspaceService;/*** 工…

★WIN10计算器程序员版的使用说明(详细)

主界面 拉动边框的角&#xff1a; 1.进制转换 HEX(hexadecimal)&#xff1a;显示十六进制&#xff0c;DEC(decimal)&#xff1a;显示十进制&#xff0c;OCT(octonary)&#xff1a;显示八进制&#xff0c;BIN(binary):显示二进制 例如&#xff1a; 选中HEX 0~9&#xff0c;A…

Genymotion adb shell

Genymotion 账户是 qq邮箱 参考 Ubuntu 20.04 安装 Android 模拟器 Genymotion https://www.zzzmh.cn/post/553cd96d4e47490a90b3302a76a93c0d Genymotion adb shell adb shell C:\Program Files\Genymobile\Genymotion\tools>adb shell lsusb Bus 001 Device 001: ID …

【Bug分析】Keil报错:error: #18:expected a “)“问题解决

【Bug分析】Keil报错&#xff1a;error: #18:expected a “&#xff09;”问题解决 前言bug查找bug解决方法小结 前言 keil编译时出现一个问题&#xff0c;缺少一个右括号。然后仔细查看代码&#xff0c;并没有括号缺失。 如下&#xff0c;代码括号正常。 bug查找 站内文章…