数据结构之栈的讲解

news2024/11/19 1:54:53

 

 💕"

春宵一刻值千金,花有清香月有阴。

"💕

作者:Mylvzi 

 文章主要内容:leetcode刷题之哈希表的应用(1) 

1.栈的概念

  栈是一种只允许在一端(栈顶)进行数据操作的数据结构,具有“后进先出”的特性,也叫做Last in First Out

最常见的现实生活中的例子就是压子弹  只能一端压子弹

2.栈的模拟实现

  我们想想什么可以实现栈的操作呢?我们知道,栈最大的特性就行只能在一端进行数据操作,使用数组可以更好的模拟栈

  数组的末尾就是我的栈顶,操作栈顶就是操作数组的最后一个元素,而数组最后一个元素的添加,删除都很方便!!!

 1.使用数组模拟

public class MyStack {
    /**
     * 栈的实现一:用数组实现栈
     */
    private int[] elem;
    private int usedSize;

    private static final int DEFAULTCAPACITY = 10;

    public MyStack() {
        this.elem = new int[DEFAULTCAPACITY];
    }

    public MyStack(int size) {
        this.elem = new int[size];
    }

    public void push(int val) {
        if (isFull()) {
            this.elem = Arrays.copyOf(this.elem,2*this.elem.length);
        }

        this.elem[usedSize] = val;
        this.usedSize++;
    }

    private boolean isFull() {
        return this.usedSize == this.elem.length;
/*        if (this.elem.length == this.usedSize) {
            return true;
        }

        return false;*/
    }

    public int pop() {
        if (isEmpty()) {
            throw new StackEmptyException("栈区之内不含有数据,无法删除");
        }

//        this.usedSize--;
//        return this.elem[usedSize];

        int oldVal = this.elem[usedSize-1];
        this.usedSize--;
        return oldVal;
    }

    public int peek() {
        if (isEmpty()) {
            throw new StackEmptyException("栈区之内不含有数据,无法删除");
        }

        return this.elem[usedSize-1];
    }

    public boolean isEmpty() {

        return this.usedSize == 0;
/*        if (this.usedSize == 0) {
            return true;
        }

        return false;*/
    }

}

2.使用链表模拟

当然除了使用数组模拟栈,使用链表也可以实现栈的功能(Java中的LinkedList本质上是一个无头双向非循环链表)

class Mystack3 {
    // 使用链表模拟栈
    /**
     * 栈只能在一端进行数据的操作
     * 在这里我们只在链表的last进行数据的操作
     */
    LinkedList<Integer> mystack = new LinkedList<>();

    // push
    public void push(int data) {
        mystack.addLast(data);
    }

    // pop
    public int pop() {
        if(mystack.isEmpty()) {
            return -1;// 抛异常也可以
        }
        return mystack.pollLast();
    }

    public int peek() {
        return mystack.peekLast();
    }

    public static void main(String[] args) {
        Mystack3 mystack3 = new Mystack3();
        mystack3.push(1);
        mystack3.push(2);
        mystack3.push(3);

        System.out.println(mystack3.pop());// 3
        System.out.println(mystack3.peek());// 2
    }
}

3.Java中的栈Stack

  Java中提供了现成的栈供我们使用

代码演示 

// 栈的创建  栈在Java中就是一个类!!!
        Stack<Integer> stack = new Stack<>();
        stack.push(1);
        stack.push(2);
        stack.push(3);
        stack.push(4);

        // 使用构造器
        Iterator<Integer> it= stack.iterator();
        while (it.hasNext()) {
            System.out.print(it.next()+" ");// 1 2 3 4
        }
        System.out.println();
        System.out.println("============================");
        // 重写了toString方法  直接传对象 即可打印内容
        System.out.println(stack);// 1 2 3 4

        // pop会删除栈顶元素
        stack.pop();
        System.out.println(stack);// 1 2 3

        // peek  瞄一眼  不会把top删除
        int x = stack.peek();
        System.out.println(x);// 3
    }

 4.栈的应用场景

1.括号匹配问题

20. 有效的括号 - 力扣(LeetCode)icon-default.png?t=N7T8https://leetcode.cn/problems/valid-parentheses/

分析:

代码实现:

class Solution {
    public static boolean isValid(String s) {
        if(s.length() % 2 != 0) return false;
        Stack<Character> stack = new Stack<>();

        for (int i = 0; i < s.length(); i++) {
            // 获取当前字符
            char ch = s.charAt(i);
            // 左括号
            if(ch == '(' || ch == '{' || ch == '[') {
                stack.push(ch);
            }else {// 右括号
                if(stack.isEmpty()) {
                   return false;
                }else {
                    // 要进行括号匹配
                    char top = stack.peek();

                    if(ch == '}' && top == '{' || ch == ')' && top == '(' ||ch == ']' && top == '[') {
                        stack.pop();
                    }else {
                        return false;
                    }
                }
            }
        }

        return stack.isEmpty();

    }
}

也可以使用顺序表实现

class Solution {
    public static boolean isValid(String s) {
        if(s.length() % 2 != 0) return false;
        List<Character> list = new ArrayList<>();

        for (int i = 0; i < s.length(); i++) {
            // 获取当前字符
            char ch = s.charAt(i);
            // 左括号
            if(ch == '(' || ch == '{' || ch == '[') {
                list.add(ch);
            }else {// 右括号
                if(list.isEmpty()) {
                   return false;
                }else {
                    // 要进行括号匹配
                    char top = list.get(list.size()-1);

                    if(ch == '}' && top == '{' || ch == ')' && top == '(' ||ch == ']' && top == '[') {
                        list.remove(list.size()-1);
                    }else {
                        return false;
                    }
                }
            }
        }

        return list.isEmpty();

    }

}

2.后缀表达式

 代码实现:

class Solution {
    public int evalRPN(String[] tokens) {
        // 遇到数字存放到栈中
        Stack<Integer> stack = new Stack<>();

        // 循环遍历所给字符串
        for(String s : tokens) {
            // 数字
            if(!isOperation(s)) {
                // 是数字就push
                stack.push(Integer.parseInt(s));
            }else {// 运算符
            // 先弹出的作右运算符  后弹出的是左运算符
                int num2 = stack.pop();
                int num1 = stack.pop();

                switch(s) {
                    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();

    }

    // 判断是否是运算符
    private boolean isOperation(String s) {
        if(s.equals("+") || s.equals("-") || s.equals("*") || s.equals("/")) {
            return true;
        }

        return false;
    }
}

 3.最小栈

力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台icon-default.png?t=N7T8https://leetcode.cn/problems/min-stack/submissions/分析思路:

代码实现:使用两个栈

    class MinStack {
        //思路1 使用两个栈
        private Stack<Integer> stack;
        private Stack<Integer> minstack;// 存放过程中的最小值


        public MinStack() {
            this.stack = new Stack<>();
            this.minstack = new Stack<>();
        }
        

        public void push(int val) {
            if(minstack.isEmpty()) {
                minstack.push(val);
            }else {
                if (val <= minstack.peek()) {
                    minstack.push(val);
            }
            }

            stack.push(val);

        }

        public void pop() {
            if(!stack.isEmpty()) {
                int top = stack.pop();
                if (top == minstack.peek()) {
                    minstack.pop();
            }
            
            }
            
        }

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

        public int getMin() {
            if (minstack.isEmpty()) {
                return -1;
            }
            return minstack.peek();
        }
    }

 思路2:使用链表实现

画图分析

代码实现

 class MinStack {
        // 使用链表实现
        private class Node{
            int val;
            int min;
            Node next = null;

            public Node(int val, int min) {
                this.val = val;
                this.min = min;
            }
        }
        
        private Node head;

        public void push(int x) {
            if(head == null) {
                head = new Node(x,x);
            }else {
                Node newNode = new Node(x,Math.min(x,head.min));
                newNode.next = head;
                head = newNode;
            }

        }

        public void pop() {
            head = head.next;
        }

        public int top() {
            return head.val;
        }

        public int getMin() {
            return head.min;
        }
    }

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

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

相关文章

一篇文章让你彻底了解Java算法「十大经典排序算法」

✍️作者简介&#xff1a;码农小北&#xff08;专注于Android、Web、TCP/IP等技术方向&#xff09; &#x1f433;博客主页&#xff1a; 开源中国、稀土掘金、51cto博客、博客园、知乎、简书、慕课网、CSDN &#x1f514;如果文章对您有一定的帮助请&#x1f449;关注✨、点赞&…

Delayed 延时任务

延时任务与定时任务的区别 延时任务&#xff0c;可以理解为定时任务的一种&#xff0c;但是他们是有区别的。 延时任务&#xff1a;将程序代码延时执行&#xff0c;执行完毕&#xff0c;即为结束。 定时任务&#xff1a;周期性执行任务。代码执行完毕后&#xff0c;并不意味着…

2023年中国AI基础设施行业发展趋势分析:AI基础设施将保持高速增长[图]

从产品形态来看&#xff0c;AI基础设施可划分为AI基础硬件和基础软件两大类。而在AI生态系统中&#xff0c;通用型和定制型AI基础设施的相互依赖性促进了广泛的AI技术应用&#xff0c;也为各行业的持续发展提供了关键支持。 AI基础设施分类 资料来源&#xff1a;共研产业咨询&…

windows11系统如何设置锁屏壁纸

1. 在开始页面里面找到设置 2. 在设置里面找到个性化 3. 按照红色圈出部分操作 个性化锁屏界面 选择 图片 浏览照片 选择一张你觉得好看的图片作为锁屏壁纸 注&#xff1a;如果需要在锁屏后的登录页面显示壁纸 请勾选第三个红圈部分

Java基本数据类型与引用类型的区别

基本数据类型存放在栈中&#xff0c;引用数据类型其具体内容存放在堆中栈中存放的是其具体内容所在内存的地址。通过变量地址可以找到变量的具体内容&#xff0c;就像通过房间号可以找到房间一样。 public class Main{public static void main(String[] args){//基本数据类型in…

Active Directory 和域名系统(DNS)的相互关系

什么是域名系统&#xff08;DNS&#xff09; 域名系统&#xff08;DNS&#xff09;&#xff0c;从一般意义上讲是一种将主机名或域名解析为相应IP地址的手段。 在 AD 的中&#xff0c;DNS 服务维护 DNS 域和子域的工作命名空间&#xff0c;这些域和子域主要有助于查找过程&am…

最新绿豆APP源码苹果CMS影视插件版本/原生JAVA源码+反编译开源+免授权

源码简介&#xff1a; 最新绿豆APP源码苹果CMS影视插件版本&#xff0c;它是原生JAVA源码反编译开源免授权&#xff0c;绿豆影视对接苹果CMS&#xff0c;它可以支持多功能自定义DIY页面布局。 1、新版绿豆视频APP视频6.1插件版反编译指南及教程 2、后端插件开源&#xff0c;可…

archery修改为不能自提自审核上线SQL

目录 背景修改代码效果参考 背景 我和同事都可以提交上线SQL&#xff0c;但是不能自己提交的SQL自己去审核通过。目前的情况是可以自提自审。 修改代码 找到/opt/archery/sql/utils/workflow_audit.py文件 ...省略...# 判断用户当前是否是可审核staticmethoddef can_revie…

windows如何查看自己的ip地址

windows如何查看自己的ip地址 1.打开控制面板 2.进入网络和internet 3.进入网络共享中心 4.点击以太网进入网络详情页&#xff0c;或邮件已连接的网络&#xff0c;点击属性 5.查看ipv4地址就是当前机器ip

prometheus基本介绍 prometheus和zabbix的区别 grafana可视化工具

一、 promethues概念prometheus介绍promethues的特点prometheus的工作原理prometheus的架构 二、promethues和zabbix的区别三、prometheus安装部署prometheus下载安装prometheus启动浏览器访问查看暴露指标将Prometheus配置为systemd管理 配置node_exporter监控项node_promethe…

深入探讨软件测试技术:方法、工具与最佳实践

&#x1f482; 个人网站:【 海拥】【神级代码资源网站】【办公神器】&#x1f91f; 基于Web端打造的&#xff1a;&#x1f449;轻量化工具创作平台&#x1f485; 想寻找共同学习交流的小伙伴&#xff0c;请点击【全栈技术交流群】 引言 软件测试是软件开发生命周期中至关重要的…

微信小程序会议OA-登录获取手机号流程登录-小程序导入微信小程序SDK(从微信小程序和会议OA登录获取手机号到登录小程序导入微信小程序SDK)

目录 获取用户昵称头像和昵称 wx.getUserProfile bindgetuserinfo 登录过程 登录-小程序 wx.checkSession wx.login wx.request 后台 准备数据表 反向生成工具生成 准备封装前端传过来的数据 小程序服器配置 导入微信小程序SDK application.yml WxProperties …

对OpenAI CEO奥特曼突然被解雇事件的一些分析

今天也来凑个热闹&#xff0c;说说OpenAI的事。本来不想写的&#xff0c;但是看到自媒体又开始胡说八道&#xff0c;所以根据我自己得到的消息和理解说一说我的看法&#xff0c;这篇文章要是有个小姐姐解说录成视频&#xff0c;那肯定火了&#xff0c;但是我现在没资源&#xf…

OpenAI政变背后是科学家创始人的悲歌

OpenAI政变背后是科学家创始人的悲歌 去年11月突然推出ChatGPT震惊世界的OpenAI&#xff0c;在整整一年后以闪电解职CEO再次震惊世界。 有不少人以为这拿的是乔布斯的剧本&#xff0c;错了&#xff0c;这其实是天才科学家奋力一击的故事。 OpenAI的灵魂人物不是CEO Sam Al…

Vue3入门(与Vue2进行对比)

1. Vue2 选项式 API vs Vue3 组合式API 特点&#xff1a; 代码量变少分散式维护变成集中式维护 2. Vue3的优势 使用create-vue搭建Vue3项目 1. 认识create-vue create-vue是Vue官方新的脚手架工具&#xff0c;底层切换到了 vite &#xff08;下一代前端工具链&#xff09;&…

2023APMCM亚太杯/小美赛数学建模竞赛优秀论文模板分享

一、模板介绍 二、注意事项 将论文划分小节时&#xff0c;应避免在小节中出现大段的文字叙述&#xff0c;这样的叙述会妨碍评委在浏览论文时掌握论文的要点。重要的句子&#xff0c;包括首次定义的概念&#xff0c;用黑体书写。 重要的数学公式应另起新行单独列出。建模所用的…

使用activiti部署提示不是 ‘NCName‘ 的有效值

排查发现是整个流程图的&#xff0c;流程名称没有填写 修改之后就可以了

Redis篇---第十二篇

系列文章目录 文章目录 系列文章目录前言一、Memcache与Redis的区别都有哪些?二、单线程的redis为什么这么快三、redis的数据类型,以及每种数据类型的使用场景前言 前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站,这篇…

大数据基础设施搭建 - Kafka(with ZooKeeper)

文章目录 一、简介二、单机部署2.1 上传压缩包2.2 解压压缩包2.3 修改配置文件&#xff08;1&#xff09;配置zookeeper地址&#xff08;2&#xff09;修改kafka运行日志(数据)存储路径 2.4 配置环境变量2.5 启动/关闭2.6 测试&#xff08;1&#xff09;查看当前服务器中的所有…

Wireshark的数据包它来啦!

通过Wireshark工具&#xff0c;可以轻松的看到网卡的数据信息。通过Wireshark显示的数据包内容信息&#xff0c;通常分七栏&#xff0c;介绍一下&#xff1a; 1No.&#xff1a; 数据包编号。 2.Time Time显示时间&#xff0c;以1号数据包发生开始计时。 3.Source Source显示内容…