【Java】Stack和Queue的使用

news2024/12/24 8:55:04

文章目录

  • 一、栈
    • 1.1 什么是栈
    • 1.2 栈的模拟实现
  • 二、Java中的Stack
    • 2.1 构造方法
    • 2.2 操作方法
    • 2.3 应用场景
  • 三、队列
    • 3.1 什么是队列
    • 3.2 队列的模拟实现
  • 四、Java中的Queue
    • 4.1 实例化方法
    • 4.2 操作方法
    • 4.3 应用场景


一、栈

1.1 什么是栈

栈(Stack)是一种常见的数据结构,它遵循"后进先出"(Last-In-First-Out,LIFO)的原则。在栈中,最后添加的元素首先被访问或删除,而最先添加的元素则最后被访问或删除。

栈具有以下特点:

  1. 插入操作称为"入栈"(push):将元素添加到栈的顶部。
  2. 删除操作称为"出栈"(pop):从栈的顶部移除元素。
  3. 只能访问栈顶的元素:栈是一种限制性访问的数据结构,只允许访问或操作栈顶的元素。
  4. 栈的大小是动态的:栈的大小可以根据需要自动增长或缩小。

1.2 栈的模拟实现

import java.util.Arrays;

public class MyStack {
    private int[] elem;
    private int usedSize;

    public static final int DEFAULT_SIZE = 10;

    public MyStack(){
        elem = new int[DEFAULT_SIZE];
    }

    public void push(int val){
        // 如果栈满了就扩容
        if(isFull()){
            this.elem = Arrays.copyOf(this.elem, 2 * Arrays.stream(this.elem).sum());
        }

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

    private boolean isFull(){
        return usedSize == elem.length;
    }

    private boolean isEmpty(){
        return usedSize == 0;
    }

    public int pop(){
        if(usedSize == 0){
            throw new MyEmptyException("栈已经空!");
        }
        return elem[--usedSize];
    }

    public int size(){
        return usedSize;
    }

    public int peek(){
        if (isEmpty()){
            throw new MyEmptyException("栈已经空!");
        }
        return elem[usedSize - 1];
    }
}

二、Java中的Stack

在Java中,Stack类是一个继承自Vector类的类,它实现了一个后进先出(LIFO)的堆栈数据结构。Stack类提供了一些方法来实现栈的常见操作,例如压栈(push)、弹栈(pop)、查看栈顶元素(peek)等。

Stack的继承体系如图:

2.1 构造方法

在Java中,Stack类提供了以下几个构造方法:

  1. Stack():创建一个空的Stack对象。
Stack<String> stack = new Stack<>();
  1. Stack(Collection<? extends E> c):创建一个包含指定集合中的元素的Stack对象。集合中的元素将按照迭代器返回的顺序添加到Stack中。
List<String> collection = new ArrayList<>();
collection.add("Element 1");
collection.add("Element 2");
Stack<String> stack = new Stack<>(collection);

另外,需要注意的是,Stack类在Java 1.0中引入,但自Java 1.6起,官方推荐使用更加通用的Deque接口(如ArrayDeque或LinkedList)来代替Stack类,因为Deque提供了更丰富的操作方法,并且更加高效。

2.2 操作方法

Stack类提供了一些常见的操作方法,可以用于实现栈的功能。以下是一些常用的Stack操作方法:

  1. push(E item):将元素item压入栈顶。
Stack<String> stack = new Stack<>();
stack.push("Element 1");
stack.push("Element 2");
  1. pop():弹出并返回栈顶的元素。
Stack<String> stack = new Stack<>();
stack.push("Element 1");
stack.push("Element 2");
String topElement = stack.pop(); // 返回"Element 2",栈顶的元素被弹出
  1. peek():返回栈顶的元素,但不对栈进行修改。
Stack<String> stack = new Stack<>();
stack.push("Element 1");
stack.push("Element 2");
String topElement = stack.peek(); // 返回"Element 2",栈顶的元素不会被弹出
  1. empty():检查栈是否为空。
Stack<String> stack = new Stack<>();
boolean isEmpty = stack.empty(); // 返回true,栈为空
  1. search(Object o):查找元素o在栈中的位置,返回距离栈顶的距离(栈顶元素的位置为1,依次递增)。
Stack<String> stack = new Stack<>();
stack.push("Element 1");
stack.push("Element 2");
int position = stack.search("Element 1"); // 返回2,"Element 1"距离栈顶的位置为2

除了上述方法外,Stack类还继承了Vector类的其他方法,例如size()、isEmpty()、clear()等。

另外,由于Stack类是线程安全的,使用同步方法来实现的,而在Java的并发编程中,建议使用更高效的并发类(如ConcurrentLinkedDeque)代替Stack类。

2.3 应用场景

  1. 括号匹配问题
class Solution {
    public boolean isValid(String s) {
        Stack<Character> stack = new Stack<>();

        for (char ch : s.toCharArray()) {
            if(ch == '('){
                stack.push(')');
            } else if (ch == '{') {
                stack.push('}');
            } else if (ch == '[') {
                stack.push(']');
            } else if(stack.isEmpty() || ch != stack.pop()) {
                return false;
            }
        }

        return stack.isEmpty();
    }
}
  1. 逆波兰表达式求值
class Solution {
    
    // tokens = ["2","1","+","3","*"] 9
    public int evalRPN(String[] tokens) {
        Stack<Integer> stack = new Stack<>();

        for (String str : tokens) {
            switch (str) {
                case "+" -> {
                    int right = stack.pop();
                    int left = stack.pop();
                    stack.push(left + right);
                }
                case "-" -> {
                    int right = stack.pop();
                    int left = stack.pop();
                    stack.push(left - right);
                }
                case "*" -> {
                    int right = stack.pop();
                    int left = stack.pop();
                    stack.push(left * right);
                }
                case "/" -> {
                    int right = stack.pop();
                    int left = stack.pop();
                    stack.push(left / right);
                }
                default -> {
                    Integer integer = Integer.valueOf(str);
                    stack.push(integer);
                }
            }
        }
        return stack.pop();
    }
}

三、队列

3.1 什么是队列

队列(Queue)是一种常见的数据结构,它遵循"先进先出"(First-In-First-Out,FIFO)的原则。在队列中,最先添加的元素首先被访问或删除,而最后添加的元素则最后被访问或删除。

队列具有以下特点:

  1. 插入操作称为"入队"(enqueue):将元素添加到队列的末尾。
  2. 删除操作称为"出队"(dequeue):从队列的头部移除元素。
  3. 只能访问队列头部和尾部的元素:队列是一种限制性访问的数据结构,只允许访问或操作队列的头部和尾部元素。
  4. 队列的大小是动态的:队列的大小可以根据需要自动增长或缩小。

3.2 队列的模拟实现

public class MyQueue {
    static class ListNode {
        public int val;
        public ListNode next;

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

    private ListNode head; // 队头出
    private ListNode tail; // 队尾入

    public void offer(int val) {
        if (head == null){
            head = new ListNode(val);
            tail = head;
        } else {
            ListNode node = new ListNode(val);
            tail.next = node;
            tail = node;
        }
    }

    public int poll() {

        if(isEmpty()){
            throw new MyEmptyException("队列为空!");
        }

        int tmp = head.val;
        head = head.next;
        if (head == null)
            tail = null;
        return tmp;
    }

    public int peek() {
        if(isEmpty()){
            throw new MyEmptyException("队列为空!");
        }
        return head.val;
    }

    public int size() {
        if(isEmpty()){
            return 0;
        }

        int cnt = 0;
        ListNode cur = head;
        while (cur != null){
            cnt++;
            cur = cur.next;
        }
        return cnt;
    }

    public boolean isEmpty() {
        return head == null;
    }

    public void display(){
        ListNode cur = head;
        while (cur != null){
            System.out.print(cur.val + " ");
            cur = cur.next;
        }
        System.out.println();
    }
}

四、Java中的Queue

在Java中,Queue是一个接口,它表示一种先进先出(FIFO)的队列数据结构。它是Java集合框架的一部分,定义了一些方法来操作队列。Queue接口的常见实现类包括LinkedList和ArrayDeque。其继承体系如下:

4.1 实例化方法

Queue接口本身是一个接口,不能直接实例化。在Java中,我们可以使用具体的实现类来创建Queue对象,常用的实现类有LinkedList和ArrayDeque。

  1. LinkedList实现的Queue:
Queue<String> queue = new LinkedList<>();
  1. ArrayDeque实现的Queue:
Queue<String> queue = new ArrayDeque<>();

这些构造方法创建了一个空的Queue对象,可以根据需要将元素添加到队列中。

4.2 操作方法

Queue接口提供了一系列方法来操作队列。以下是Queue接口的一些常见操作方法:

  1. add(E e):将元素e插入队列的尾部,如果成功则返回true,如果队列已满则抛出异常。
Queue<String> queue = new LinkedList<>();
boolean result = queue.add("Element 1");
  1. offer(E e):将元素e插入队列的尾部,如果成功则返回true,如果队列已满则返回false。
Queue<String> queue = new LinkedList<>();
boolean result = queue.offer("Element 1");
  1. remove():移除并返回队列头部的元素,如果队列为空则抛出异常。
Queue<String> queue = new LinkedList<>();
String element = queue.remove();
  1. poll():移除并返回队列头部的元素,如果队列为空则返回null。
Queue<String> queue = new LinkedList<>();
String element = queue.poll();
  1. element():返回队列头部的元素,如果队列为空则抛出异常。
Queue<String> queue = new LinkedList<>();
String element = queue.element();
  1. peek():返回队列头部的元素,如果队列为空则返回null。
Queue<String> queue = new LinkedList<>();
String element = queue.peek();

此外,Queue接口还继承了Collection接口和Iterable接口中的方法,例如size()、isEmpty()、clear()、iterator()等。

4.3 应用场景

  1. 队列实现栈
// 两个队列
// 入栈:入到不为空的队列
// 出栈:找到不为空的队列,出size - 1个元素到空队列,返回最后一个元素

// 使用队列实现栈
class MyStack {
    private Queue<Integer> queue1;
    private Queue<Integer> queue2;

    public MyStack() {
        queue1 = new LinkedList<>();
        queue2 = new LinkedList<>();
    }
    
    public void push(int x) {
        // 两个队列都为空的时候
        if(empty()){
            queue1.offer(x);
            return;
        }


        if(queue1.isEmpty()){
            queue2.offer(x);
        } else {
            queue1.offer(x);
        }
    }
    
    public int pop() {
        if(empty()){
            return -1;
        }

        if(queue1.isEmpty()){
            int size = queue2.size();
            while (size - 1 != 0){
                queue1.offer(queue2.poll());
                size--;
            }
            return queue2.poll();
        } else {
            int size = queue1.size();
            while (size - 1 != 0){
                queue2.offer(queue1.poll());
                size--;
            }
            return queue1.poll();
        }
    }
    
    public int top() {
        int tmp = pop();
        push(tmp);
        return tmp;
    }
    
    public boolean empty() {
        return queue1.isEmpty() && queue2.isEmpty();
    }
}
  1. 栈实现队列
class MyQueue {

    private Stack<Integer> inStack; // 入栈
    private 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 -1;
        }

        if (outStack.isEmpty()) {
            while (!inStack.empty()) {
                outStack.push(inStack.pop());
            }
        }
        return outStack.pop();
    }
    
    public int peek() {
        if(outStack.empty()){
            while (!inStack.empty()){
                outStack.push(inStack.pop());
            }
        }

        return outStack.peek();
    }
    
    public boolean empty() {
        return inStack.isEmpty() && outStack.isEmpty();
    }
}

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

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

相关文章

VSCODE VUE3 element-ui plaus 环境搭建

目录 一、VUE 1、安装VUE 2、创建项目 二、Element Plus 1、在项目目录中安装 Element Plus&#xff0c;执行 2、引入element 三、vscode 中运行 1、打开项目文件夹 2、点击debug&#xff0c;运行 1&#xff09;、首次lanch chrome时 2&#xff09;、lanch node.js …

【python】pycharm配置Github Copilot

1.获取github的ip import socket from urllib.parse import urlparse# 通过URL获取目标服务器IP和端口号 def get_server_ip_and_port(url):# 解析URL获取域名和端口号parsed_url urlparse(url)domain parsed_url.netlocport parsed_url.port or 80try:# 进行域名解析&…

基于matlab使用光学字符识别技术识别文本(附源码)

一、前言 此示例演示如何使用计算机视觉工具箱中的函数执行光学字符识别。 二、实例 识别图像中的文本在许多计算机视觉应用程序中非常有用&#xff0c;例如图像搜索、文档分析和机器人导航。该函数提供了一种将文本识别功能添加到各种应用程序的简单方法。 函数返回已识别的…

VS2022配置OpenCV4.7.0

1、下载并解压OpenCV OpenCV与VC版本的对应关系信息&#xff1a;OpenCV解压后在\opencv\build\x64文件夹下可以看到如下文件夹&#xff1a; 其中&#xff1a;vc16 Visual Studio 2019 2、配置环境变量 双击Path进入【编辑环境变量】界面&#xff0c;新建—>浏览将opencv\b…

半导体自动化专用风机风棒的特点

半导体自动化专用离子风机是一种专门用于半导体工业领域的设备。它采用了离子风技术&#xff0c;通过产生带电离子来达到除尘、静电消除、表面清洁等功能。 半导体生产过程中&#xff0c;电子元器件的制造需要保持高度的清洁和静电控制。离子风机通过释放正负电离子对空气中的…

剑指 Offer 41: 数据流中的中位数

这道题用的优先队列非常好&#xff0c;一边维护一个左半边&#xff0c;一边维护一个右半边。&#xff08;注意&#xff1a;较大的一半不用改变规则&#xff0c;因为出都是默认出小的&#xff09;。然后每次和小的队列开头的数比较&#xff08;即偏小那个队列的最大值&#xff0…

【广州华锐互动】医疗健康数字孪生可视化系统有哪些功能?

医疗健康数字孪生可视化系统是一种将现实世界中的医疗设备、医院环境和患者数据与虚拟世界中的数字化副本相连接的技术。通过收集和分析实时数据&#xff0c;医疗健康数字孪生可视化系统可以帮助医疗机构提高运行效率、降低成本、优化资源分配&#xff0c;并为患者提供更好的诊…

2023工业自动化发展十大趋势

凭借着多年的行业经验和各种数据的汇总,推断出了在未来几年中,制药、服务和农业行业可能会在使用协作机器人技术方面处于重要地位,并且预估工业机器人自动化行业会有以下十大趋势变化。 1、对智能传感器的需求增加 质量检查是所有行业的关键组成部分,分析从食品到电话保护…

Spring MVC相关注解运用 —— 下篇

目录 一、ResponseBody、RestController 1.1. JSP页面 1.2 放行静态资源 1.3 编写实体类 1.4 控制器方法 1.5 添加依赖 1.6 测试结果 1.7 RestController 二、静态资源映射 2.1 配置静态资源筛查器 2.2 配置静态资源资源映射器 2.3 配置默认Servlet处理静态资源 三…

Element UI日期组件-选择月份具体到当月最后一天

Element已有的月份选择组件&#xff0c;只能展示开始月份的1号到结束月份的1号&#xff08;例如&#xff1a;开始月份为3月&#xff0c;结束月份为3月&#xff0c;input框内只能展示2023-03-01至2023-03-01&#xff09;&#xff0c;但是我们的需求想要展示的是2023-03-01至2023…

AIGC - Stable Diffusion 超分辨率插件 StableSR v2 (768x768) 配置与使用

欢迎关注我的CSDN&#xff1a;https://spike.blog.csdn.net/ 本文地址&#xff1a;https://spike.blog.csdn.net/article/details/131582734 论文&#xff1a;Exploiting Diffusion Prior for Real-World Image Super-Resolution StableSR 算法提出了一种新颖的方法&#xff0…

【Java项目】Vue+ElementUI+Ceph实现多类型文件上传功能

文章目录 前端后端Java 前端 ElementUI 文件上传的页面使用的是ElementUI的 下面是index.vue页面&#xff0c;有点小bug&#xff08;但是我真改不动&#xff0c;前端还在学习中&#xff09; <template><div><el-uploadclass"upload-demo":action&qu…

1.浮动 ( float )

学习目标&#xff1a; 1.1 传统网页布局的三种方式 网页布局的本质——用 CSS来摆放盒子&#xff0c;把盒子摆放到相应位置 CSS提供了三种传统布局方式(简单说,就是盒子如何进行排列顺序) : ●普通流(标准流) ●浮动 ●定位 1.2 标准流(普通流/文档流) 所谓的标准流&#xf…

Go基础知识学习

文章目录 介绍背景和起源特点和优势 安装和设置下载和安装Go语言配置Go环境变量GOROOT和GOPATHGOPROXY 编辑器、IDE等工具Hello, World!基本结构和数据类型关键字标识符变量常量基本数据类型类型转换 控制流程数组和切片数组切片 函数定义和调用函数函数参数和返回值 结构体和方…

Jmeter学习笔记

Jmeter学习笔记 1、安装 1.1、下载 官方地址&#xff1a;https://archive.apache.org/dist/jmeter/binaries/ 1.2、环境变量 此电脑 --> 属性 --> 高级系统设置 --> 环境变量 设置JMETER_HOME&#xff0c;值为jmeter的路径D:\apache-jmeter-4.0 设置Path&…

【设计模式】第十四章:策略模式详解及应用案例

系列文章 【设计模式】七大设计原则 【设计模式】第一章&#xff1a;单例模式 【设计模式】第二章&#xff1a;工厂模式 【设计模式】第三章&#xff1a;建造者模式 【设计模式】第四章&#xff1a;原型模式 【设计模式】第五章&#xff1a;适配器模式 【设计模式】第六章&…

scanpy sc.pp.normalize_per_cell bug

今天遇到一个很奇怪的bug, 当今天跑covid_atlas数据集的时候&#xff0c;在123服务器总是报错&#xff0c;但是我记得在122服务器上是跑过没问题的 最终的测试结果如下 import scanpy as sc import numpy as np from QUEST import QUEST from QUEST.utils import get_free_…

【MySQL】简介 MySQL 事务

一、事务 ACID 原则 什么是事务呢&#xff1f;事务通常是一个或一组 SQL 组成的&#xff0c;组成一个事务的 SQL 一般都是一个业务操作&#xff0c;例如下单操作&#xff1a;【扣库存数量、增加订单详情记录、插入物流信息】&#xff0c;这一组 SQL 就可以组成一个事务。 而数据…

推特开始限制用户可以阅读的推文数量

推特正在限制用户可以阅读的推文数量&#xff0c;因为埃隆马斯克 (Elon Musk) 拥有的服务长期中断&#xff0c;阻碍了用户跟踪新帖子的能力。 在一条推文中&#xff0c;马斯克详细介绍了修改后的使用配额。 经过验证的帐户持有者每天最多可以浏览 6000 个帖子&#xff0c;而未…

docker的联合文件系统 UnionFS《深入docker底层原理》

介绍 docker最大的贡献就是定义了容器镜像的分层的存储格式&#xff0c;docker镜像技术的基础是联合文件系统(UnionFS)&#xff0c;其文件系统是分层的。这样既可以充分利用共享层&#xff0c;又可以减少存储空间占用。 联合挂载系统的工作原理&#xff1a;读&#xff1a;如果…