Collection与数据结构 Stack与Queue(一): 栈与Stack

1. 栈

1.1 概念

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

1.2 栈的使用

方法功能
Stack()构造一个空的栈
E push(E e)将e入栈,并返回e
E pop()将栈顶元素出栈并返回
E peek()获取栈顶元素
int size()获取栈中有效元素个数
boolean empty()检测栈是否为空
import java.util.Stack;

public class Main {
    public static void main(String[] args) {
        //使用Stack中自带的方法
        Stack<Integer> stack = new Stack<>();
        stack.push(1);
        stack.push(2);
        stack.push(3);
        stack.push(4);//压栈
        System.out.println(stack.peek());
        System.out.println(stack.peek());//没有弹出元素,只是返回了栈顶元素
        System.out.println(stack.pop());
        System.out.println(stack.pop());//出栈
        System.out.println(stack.size());//计算栈中元素的个数
        System.out.println(stack.empty());//判断栈是否为空
        //使用Stack从Collection继承下来的方法
        Stack<Integer> stack1 = new Stack<>();
        stack1.add(1);
        stack1.add(2);
        stack1.add(3);
        stack1.add(4);//添加元素
        System.out.println(stack1.isEmpty());//判断是否为空
    }
}

运行结果:
在这里插入图片描述

1.3 栈的模拟实现

import java.util.Arrays;

public class MyStack {
    int[] array = new int[5];//默认容积为5
    int size;
    public void push(int x){
        ensureCapacity();
        array[size] = x;
        size++;
    }
    public int pop(){
        int e = peek();
        size--;
        return e;
    }
    public int peek(){
        if (!empty()){
            return array[size-1];
        }
        throw new EmptyExecption("Stack is empty.");
    }
    public boolean empty(){
        if (size == 0){
            return true;
        }
        return false;
    }
    public int size(){
        return this.size;
    }
    private void ensureCapacity(){
        if (this.array.length == size){
            this.array = Arrays.copyOf(array,array.length*2);
        }
    }
}
public class EmptyExecption extends RuntimeException{
    public EmptyExecption(String message) {
        super(message);
    }
}

2. 栈的相关面试题

2.1 括号匹配

OJ链接
在这里插入图片描述

class Solution {
        public boolean isValid(String s) {
            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.empty()){
                        return false;//如果在匹配的时候,栈为空,说明右括号赘余
                    }
                    char ch2 = stack.peek();
                    if (ch2 == '(' && c == ')'||ch2 == '[' && c == ']'||ch2 == '{' && c == '}'){
                        stack.pop();
                    }else {
                        return false;//括号不匹配
                    }
                }
            }
            return stack.empty();//遍历完了,栈中还有元素,说明左括号赘余
        }
    }

上述代码逻辑较为复杂,我们通过一张图来理清楚:
在这里插入图片描述

2.2 逆波兰表达式求值

OJ链接
在这里插入图片描述

class Solution2 {
        public int evalRPN(String[] tokens) {
            Stack<Integer> stack = new Stack<>();
            for (int i = 0; i < tokens.length; i++) {
                String s = tokens[i];
                if (isOperation(s)){
                    int x1 = stack.pop();
                    int x2 = stack.pop();//把两个数字出栈
                    int x = 0;
                    if (s.equals("+")){
                        x = x1+x2;
                    } else if (s.equals("-")) {
                        x = x2-x1;//注意逆波兰表达式,先从栈中弹出的放在后面
                    } else if (s.equals("/")) {
                        x = x2/x1;
                    }else {
                        x = x1*x2;
                    }
                    stack.push(x);//计算之后放回栈中
                }else {
                    stack.push(Integer.parseInt(s));//将字符串转化为数字
                }
            }
            return stack.pop();//最后栈中的值就是最终的值
        }
		private boolean isOperation(String s){//判断是否为加减乘除
		            if (s.equals("+") ||s.equals("-")||s.equals("*")||s.equals("/")){
		                return true;
		            }
		            return false;
		        }
		    }

拓展: 中缀表达式转后缀表达式,现给出中缀表达式( 1 + 2 ) * ( 3 + 4 ),转为后缀(逆波兰)表达式过程如下.
在这里插入图片描述
其实我们在电脑中或者是手机上经常用到的计算器就是这样的原理.计算机中的计算器是无法直接识别中缀表达式的,都是先转为后缀表达式,再进行运算的.

在这里插入图片描述

2.3 入栈出栈顺序匹配

OJ链接

在这里插入图片描述

class Solution3 {
        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.empty() &&stack.peek() == popped[j]){//每放入栈中一个元素,就和popped比较是否相等
                    stack.pop();//如果相等,出栈
                    j++;//popped下标向后走
                }
            }
            while (j < popped.length){//i把push全部遍历完之后,Stack中可能还有元素没有与popped中的匹配完成
                if (stack.peek() == popped[j]){
                    stack.pop();
                    j++;//继续匹配操作
                }else {
                    return false;//一旦有一个不匹配,说明popped的出栈顺序是错误的
                }
            }
            return true;//全部匹配完成,返回true
        }
    }

2.4 在常数时间复杂度的情况下寻找栈中最小元素

OJ链接

在这里插入图片描述

class MinStack {
        Stack<Integer> stack;
        Stack<Integer> stack1;
        public MinStack() {
            stack = new Stack<>();//放所有要入栈的元素
            stack1 = new Stack<>();//放较小元素,栈顶元素是入stack所有元素中最小的
        }

        public void push(int val) {
            stack.push(val);
            if (stack1.empty()){//如果最小栈中没有元素,就把第一个元素放入
                stack1.push(val);
            }else{
                if(stack1.peek() >= val){//和最小栈的栈顶元素比较大小,stack1的栈顶大于等于val的时候,入栈
                    //等于的时候也要放入,否则pop的时候,最小栈和普通栈会不匹配
                    stack1.push(val);
                }
            }
        }

        public void pop() {
            if (Objects.equals(stack.pop(), stack1.peek())){
                stack1.pop();//两栈元素相等的时候都弹出,否则只弹出普通栈中的元素
            }
        }

        public int top() {
            return stack.peek();//返回普通栈栈顶元素
        }

        public int getMin() {
            return stack1.peek();//直接返回最小栈的栈顶元素
        }
    }

2.5 逆序打印列表

方法一:递归法

void printList(Node head){
    if(null != head){//遇到null的时候往回递归
        printList(head.next);//没有遇到null的时候,向后递归
        System.out.print(head.val + " ");
   }
}

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

方法二:Stack法

 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 + " ");
   }
}

从上述代码,我们可以得到一个结论,栈可以替代递归思想,在我们后期学习二叉树的时候,在非递归遍历二叉树的时候,我们会频繁地用到栈.

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【029】基于ssm+小程序实现的理发店预约系统

作者主页&#xff1a;Java码库 主营内容&#xff1a;SpringBoot、Vue、SSM、HLMT、Jsp、PHP、Nodejs、Python、爬虫、数据可视化、小程序、安卓app等设计与开发。 收藏点赞不迷路 关注作者有好处 文末获取源码 技术选型 【后端】&#xff1a;Java 【框架】&#xff1a;ssm 【…

Hadoop: word count,并将reduce结果写入ES

一、依赖&#xff0c;其中ES版本为7.6.2 <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0"xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation"http…

[StartingPoint][Tier0]Mongod

Task 1 How many TCP ports are open on the machine? (机器上打开了多少个 TCP 端口&#xff1f;) Example: $ sudo nmap -sS -T4 10.129.222.112 -p 27017,22 2 Task 2 Which service is running on port 27017 of the remote host? (哪个服务正在远程主机的端口 270…

Hippo4j线程池实现技术

文章目录 &#x1f50a;博主介绍&#x1f964;本文内容部署运行模式集成线程池监控配置参数默认配置 &#x1f4e2;文章总结&#x1f4e5;博主目标 &#x1f50a;博主介绍 &#x1f31f;我是廖志伟&#xff0c;一名Java开发工程师、Java领域优质创作者、CSDN博客专家、51CTO专家…

基于Java课程选课系统设计与实现(源码+部署文档)

博主介绍&#xff1a; ✌至今服务客户已经1000、专注于Java技术领域、项目定制、技术答疑、开发工具、毕业项目实战 ✌ &#x1f345; 文末获取源码联系 &#x1f345; &#x1f447;&#x1f3fb; 精彩专栏 推荐订阅 &#x1f447;&#x1f3fb; 不然下次找不到 Java项目精品实…

KIl5:Stm32L071下载出现flash download faild “cortex-m0+“的解决方法

首先看看有没有芯片&#xff0c;没有芯片下载一下 下载并在device选择对应的芯片 选择调试器 选择flash

gpt4.0中文版

我愿把这个网站成为全球最强AI网站&#xff01;弄100多个AI伺候你&#xff1f;&#xff1f; 家人们&#xff0c;你们猜我发现了什么牛逼的AI网站&#xff1f;&#xff1f; 直接上图&#xff1a; 编辑 这个网站&#xff0c;聚合了国内外100多个顶尖的AI&#xff0c;包括了Op…

入门用Hive构建数据仓库

在当今数据爆炸的时代&#xff0c;构建高效的数据仓库是企业实现数据驱动决策的关键。Apache Hive 是一个基于 Hadoop 的数据仓库工具&#xff0c;可以轻松地进行数据存储、查询和分析。本文将介绍什么是 Hive、为什么选择 Hive 构建数据仓库、如何搭建 Hive 环境以及如何在 Hi…

我认识的Git-史上最强的版本控制系统

大家好&#xff01; 欢迎大家来一起交流Git使用心得&#xff0c;相信很多同事对Git都很熟悉了&#xff0c;如果下面说的有错误的“知识点”&#xff0c;欢迎批评指正。 初识Git 我认识Git已经很多年了&#xff08;我在有道云笔记里面“Git”文件夹的创建时间是&#xff1a; …

sky06笔记下

1.边沿检测 检测输入信号din的上升沿&#xff0c;并输出pulse module edge_check ( clk, rstn, din, pulse ); input wire clk,rstn; input wire din; output reg pulse;wire din_dly;always (posedge clk or negedge rstn)beginif(!rstn)din_dly < 1b0;elsedin_dly < d…

JS-11A/11时间继电器 板前接线 JOSEF约瑟

系列型号&#xff1a; JS-11A/11集成电路时间继电器&#xff1b;JS-11A/12集成电路时间继电器&#xff1b; JS-11A/13集成电路时间继电器&#xff1b;JS-11A/136集成电路时间继电器&#xff1b; JS-11A/137集成电路时间继电器&#xff1b;JS-11A/22集成电路时间继电器&#…

【C语言】_文件内容操作:随机读写

目录 1. fseek 1.1 随机读文件 1.2 随机写文件 2. ftell 3. rewind 当以读方式打开一个存在且存有内容的文件时&#xff0c;文件指针会默认指向第一个元素。以在test4.txt文件中存储abcdef为例&#xff1a; int main() {//打开文件FILE* pf fopen("E:\\C_文件操作…

数学知识--(质数,约数)

本文用于个人算法竞赛学习&#xff0c;仅供参考 目录 一.质数的判定 二.分解质因数 三.质数筛 1.朴素筛法 2.埃氏筛法 3.线性筛法 四.约数 1.求一个数的所有约数 2.约数个数和约数之和 3.欧几里得算法&#xff08;辗转相除法&#xff09;-- 求最大公约数 一.质数的判定 …

JWT--study

JWT 1、简介 2、结构 头部 载荷 签证 应用 <dependency><groupId>io.jsonwebtoken</groupId><artifactId>jjwt</artifactId><version>0.9.1</version> </dependency>Token 生成 解析token package com.wang.utils;import io.…

【QT+QGIS跨平台编译】056:【pdal_lepcc+Qt跨平台编译】(一套代码、一套框架,跨平台编译)

点击查看专栏目录 文章目录 一、pdal_lepcc介绍二、pdal下载三、文件分析四、pro文件五、编译实践一、pdal_lepcc介绍 pdal_lepcc 是 PDAL(Point Data Abstraction Library)的一个插件,用于点云数据的压缩。它基于 EPCC(Entwine Point Cloud Compression)算法,提供了对点…

Linux-4 gcc和makefile

Linux编译器-gcc/g使用 1.设计样例 c语言&#xff1a;linux中用的stdc99版本--可能会出现其他问题 c&#xff1a;Linux中用的stdc11--使用c11版本 Linux没有文件格式的区分&#xff0c;但是编译器区分 gcc编译器的文件格式是filename.c g编译器的文件格式是filename.cc或者fil…

利用Spark将Kafka数据流写入HDFS

利用Spark将Kafka数据流写入HDFS 在当今的大数据时代&#xff0c;实时数据处理和分析变得越来越重要。Apache Kafka作为一个分布式流处理平台&#xff0c;已经成为处理实时数据的事实标准。而Apache Spark则是一个强大的大数据处理框架&#xff0c;它提供了对数据进行复杂处理…

可行性研究报告模板(套用)

1业务需求可行性分析 2技术可行性分析 2.1规范化原则 2.2高度的兼容性和可移植性 2.3人性化、适用性 2.4标准化统一设计原则 2.5先进安全可扩展性原则 3开发周期可行性分析 4人力资源可行性分析 5成本分析 6收益分析 7结论 所有资料获取进主页或本文末个人名片直接…

【OSTEP】并发:线程与多线程

" A flow of control within a process that consists of a PC, a register set and a stack space" 本章将介绍为单个运行进程提供的新抽象 —— 线程 (thread) 线程是 调度的一个基本单位&#xff08;basic unit of CPU scheduling&#xff09;一个单独的线程至…

RUST语言函数的定义与调用

1.定义函数 定义一个RUST函数使用fn关键字 函数定义语法: fn 函数名(参数名:参数类型,参数名:参数类型) -> 返回类型 { //函数体 } 定义一个没有参数,没有返回类型的参数 fn add() {println!("调用了add函数!"); } 定义有一个参数的函数 fn add(a:u32)…