Java栈和队列模拟实现及其方法使用

news2024/9/26 1:21:09

1. (Stack)

1.1 概念

:一种特殊的线性表,其 只允许在固定的一端进行插入和删除元素操作 。进行数据插入和删除操作的一端称为栈顶,另一端称为栈底。栈中的数据元素遵守后进先出LIFO Last In First Out )的原则。
压栈 :栈的插入操作叫做进栈 /压栈/ 入栈 入数据在栈顶
出栈 :栈的删除操作叫做出栈。 出数据在栈顶

 有点类似于我们的羽毛球筒,只能在一边取,一边放

 1.2 栈的使用

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

 代码示例:

public static void main(String[] args) {
Stack<Integer> s = new Stack();
s.push(1);
s.push(2);
s.push(3);
s.push(4);
System.out.println(s.size()); //  4
System.out.println(s.peek()); //  4
s.pop(); // 4出栈,栈顶元素变为3
System.out.println(s.pop()); // 3出栈,栈中剩余1 2
if(s.empty()){
System.out.println("栈空");
}else{
System.out.println(s.size());
}
}
Stack 继承了 Vector Vector ArrayList 类似,都是动态的顺序表,不同的是 Vector 是线程安
全的。
1.3 栈的模拟实现
import java.util.Arrays;

public class MyStack {
    int[] array;
    int size;

    public MyStack() {
        array = new int[10];
    }

    public int push(int e) {
        ensureCapacity();
            array[size++] = e;
            return e;
    }

    public int pop() {
        if(empty()) System.out.println("栈为空");
        int e = peek();
        size--;
        return e;
    }

    public int peek() {
    int e = array[size-1];
    return e;
    }

    public int size() {
        return size;
    }

    public boolean empty() {
        return 0 == size;
    }

    private void ensureCapacity() {
        if (size == array.length) {
           array = Arrays.copyOf(array, size * 2);
        }
    }
}
public class Test233 {
    public static void main(String[] args) {
        MyStack myStack = new MyStack();
        System.out.println(myStack.push(1));
        System.out.println(myStack.push(2));
        System.out.println(myStack.push(3));
        System.out.println(myStack.pop());
        System.out.println(myStack.pop());
        System.out.println(myStack.pop());
        System.out.println(myStack.empty());
    }
    }

1.3 栈的应用

1.3.1 用栈改变序列

  若进栈序列为 1,2,3,4 ,进栈过程中可以出栈,则下列不可能的一个出栈序列是()
A: 1,4,3,2 B: 2,3,4,1 C: 3,1,4,2 D: 3,4,2,1 C
一个栈的初始状态为空。现将元素 1 2 3 4 5 A B C D E 依次入栈,然后再依次出栈,则元素出栈的顺序是( )。/// B
A: 12345ABCDE B: EDCBA54321 C: ABCDE12345 D: 54321EDCBA

1.3.2 递归转换为循环

// 递归方式
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. 栈、虚拟机栈、栈帧的区别

 栈是一种数据结构,虚拟机栈是JVM中的一块内存,栈帧是调用方法时开辟的一块空间,栈帧也是存在与虚拟机栈中的

栈是一种通用的数据结构概念,虚拟机栈是 Java 虚拟机中的特定内存区域,而栈帧是在虚拟机栈中为方法调用开辟的一块空间,用于存储方法执行的具体状态信息。

  • 关于栈

栈作为一种数据结构,具有后进先出(LIFO)的特性。它可以在不同的场景中被实现和应用,用于存储和管理数据。

  • 虚拟机栈

在 Java 虚拟机中,虚拟机栈是一块用于支持 Java 方法执行的内存区域。每个线程都有自己独立的虚拟机栈。它主要用于存储方法调用的相关信息,如局部变量、操作数栈、动态链接、方法返回地址等。虚拟机栈的大小可以是固定的,也可以是动态扩展的。如果栈空间不足,可能会导致栈溢出错误。

  • 栈帧

当一个方法被调用时,会在虚拟机栈中为该方法创建一个栈帧。栈帧是虚拟机栈中的一个逻辑单元,它包含了方法执行所需的各种信息。具体来说,栈帧中通常包括局部变量表、操作数栈、动态链接、方法返回地址等部分。局部变量表用于存储方法的局部变量,操作数栈用于方法执行过程中的运算操作,动态链接用于支持方法的动态绑定,方法返回地址则记录了方法执行完毕后应该返回的位置。当方法执行完毕时,对应的栈帧会被弹出虚拟机栈,释放其占用的空间。

综上所述,栈是一种通用的数据结构概念,虚拟机栈是 Java 虚拟机中的特定内存区域,而栈帧是在虚拟机栈中为方法调用开辟的一块空间,用于存储方法执行的具体状态信息。

3. 队列(Queue)

3.1 概念

队列 只允许在一端进行插入数据操作,在另一端进行删除数据操作的特殊线性表 队列具有先进先出 FIFO(First In First Out) 入队列:进行插入操作的一端称为 队尾( Tail/Rear 出队列:进行删除操作的一端称为 队头 Head/Front

 Queue是个接口,在实例化时必须实例化LinkedList的对象,因为LinkedList实现了Queue接口。

3.2 队列的方法及其使用与定义

Java 中, Queue 是个接口,底层是通过链表实现 的。
boolean offer(E e)                     入队列
E poll()                                      出队列
peek()                                       获取队头元素
int size()                                    获取队列中有效元素个数
boolean isEmpty()                    检测队列是否为空
  Queue<Integer> q = new LinkedList<>();
            q.offer(1);
            q.offer(2);
            q.offer(3);
            q.offer(4);
            q.offer(5); // 从队尾入队列
            System.out.println(q.size());
            System.out.println(q.peek()); // 获取队头元素
            q.poll();
            System.out.println(q.poll()); // 从队头出队列,并将删除的元素返回
            if(q.isEmpty()){
                System.out.println("队列空");
            }else{
                System.out.println(q.size());
            }
        }

3.3 队列模拟实现

队列的底层是双向链表,双向链表的实现队列更加便利

public class MyQueue {
    // 双向链表节点
    public static class ListNode{
        ListNode next;
        ListNode prev;
        int value;
        ListNode(int value){
            this.value = value;
        }
    }
    ListNode first; // 队头
    ListNode last; // 队尾
    int size = 0;
    // 入队列---向双向链表位置插入新节点
    public void offer(int e){
        ListNode newNode = new ListNode(e);
        if(first == null){
            first = newNode;
        }else{
            last.next = newNode;
            newNode.prev = last;
        }
        last = newNode;
        size++;
    }
        //队头出列
    public int poll(){
        int value = 0;
        if(first == null){
         throw new NullPointerException("first is null");
        }else if(first == last){
            last = null;
            first = null;
        }else{
            value = first.value;
            first = first.next;
            first.prev.next = null;
            first.prev = null;
        }
        size--;
        return value;
    }
    // 获取队头元素---获取链表中第一个节点的值域
    public int peek(){
        if(first == null){
            throw new NullPointerException("first is null");
        }
        return first.value;
    }
    public int size() {
        return size;
    }
    public boolean isEmpty(){
        return first == null;
    }
}
import java.util.*;

public class Test233 {
    public static void main(String[] args) {
        MyQueue myQueue = new MyQueue();
        myQueue.offer(1);
        myQueue.offer(2);
        myQueue.offer(3);
        myQueue.offer(4);
        myQueue.offer(5);
        System.out.println(myQueue.size());
        System.out.println(myQueue.poll());
        System.out.println(myQueue.poll());
        }
    }

3.4 循环队列

如图,首尾相接的叫做循环队列

 

 环形队列通常使用数组实现:

数组下标可以返回一个特定值,使其不会越界:

如何区分空与满
1. 通过添加 size 属性:如果size等于队列长度,则队列已满
2. 保留一个位置:
3. 使用标记flg:初始frongt==rear时标记为未满,再一次frongt==rear时标记为满

3.5 双端队列 (Deque)

双端队列( deque )是指允许两端都可以进行入队和出队操作的队列, deque “double ended queue” 的简称。那就说明元素可以从队头出队和入队,也可以从队尾出队和入队。
Deque 是一个接口,使用时必须创建 LinkedList 的对象。
Deque是一个接口,使用时必须创建LinkedList的对象。

3.6 模拟实现:

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Vector;

class Deque<T> {
    private List<T> data;

    public Deque() {
        data = new ArrayList<>();
    }

    public void addFront(T item) {
        data.add(0, item);
    }

    public void addRear(T item) {
        data.add(item);
    }

    public T removeFront() {
        if (isEmpty()) {
            return null;
        }
        return data.remove(0);
    }

    public T removeRear() {
        if (isEmpty()) {
            return null;
        }
        return data.remove(data.size() - 1);
    }

    public boolean isEmpty() {
        return data.isEmpty();
    }
}

public class Main {
    public static void main(String[] args) {
        Deque<Integer> deque = new Deque<>();
        deque.addFront(1);
        deque.addRear(2);
        System.out.println(deque.removeFront());
        System.out.println(deque.removeRear());
    }
}
import java.util.Deque;
import java.util.LinkedList;

public class DequeExample {
    public static void main(String[] args) {
        // 创建一个基于 LinkedList 的 Deque
        Deque<String> deque = new LinkedList<>();

        // 在双端队列的两端添加元素
        deque.addFirst("First element");
        deque.addLast("Last element");

        // 从双端队列的两端取出元素
        String first = deque.removeFirst();
        String last = deque.removeLast();

        System.out.println("First element removed: " + first);
        System.out.println("Last element removed: " + last);
    }
}

一、插入操作

  1. addFirst(E e):在双端队列的头部插入指定元素。如果插入成功则返回true,如果当前没有可用空间则抛出IllegalStateException异常。
  2. addLast(E e):在双端队列的尾部插入指定元素。如果插入成功则返回true,如果当前没有可用空间则抛出IllegalStateException异常。
  3. offerFirst(E e):在双端队列的头部插入指定元素。如果插入成功则返回true,如果当前没有可用空间则返回false
  4. offerLast(E e):在双端队列的尾部插入指定元素。如果插入成功则返回true,如果当前没有可用空间则返回false

二、移除操作

  1. removeFirst():移除并返回双端队列的头部元素。如果双端队列为空,则抛出NoSuchElementException异常。
  2. removeLast():移除并返回双端队列的尾部元素。如果双端队列为空,则抛出NoSuchElementException异常。
  3. pollFirst():移除并返回双端队列的头部元素。如果双端队列为空,则返回null
  4. pollLast():移除并返回双端队列的尾部元素。如果双端队列为空,则返回null

三、查看操作

  1. getFirst():返回双端队列的头部元素,但不删除它。如果双端队列为空,则抛出NoSuchElementException异常。
  2. getLast():返回双端队列的尾部元素,但不删除它。如果双端队列为空,则抛出NoSuchElementException异常。
  3. peekFirst():返回双端队列的头部元素,但不删除它。如果双端队列为空,则返回null
  4. peekLast():返回双端队列的尾部元素,但不删除它。如果双端队列为空,则返回null

四、其他操作

  1. size():返回双端队列中的元素个数。
  2. isEmpty():判断双端队列是否为空。
  3. contains(Object o):判断双端队列中是否包含指定元素。
  4. removeFirstOccurrence(Object o):从双端队列中移除第一次出现的指定元素。
  5. removeLastOccurrence(Object o):从双端队列中移除最后一次出现的指定元素。

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

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

相关文章

BBR 与 AIMD 共存公平性探究

一个古已有之的结论&#xff1a; deep buffer 场景&#xff0c;bbr 相对 reno/cubic 等 aimd 有优势&#xff0c;侵占性强&#xff1b;shallow buffer 场景&#xff0c;aimd 有优势&#xff0c;bbr 带宽被挤占。 本文用实例分析 why 并给出 how。 先看 deep buffer 场景 bbr…

Rust的数据类型

【图书介绍】《Rust编程与项目实战》-CSDN博客 《Rust编程与项目实战》(朱文伟&#xff0c;李建英)【摘要 书评 试读】- 京东图书 (jd.com) Rust到底值不值得学&#xff0c;之一 -CSDN博客 Rust到底值不值得学&#xff0c;之二-CSDN博客 3.5 数据类型的定义和分类 在Rust…

使用html+css+layui实现动态表格组件

1、概述 需求,表格第一列指标可配置通过后端api传进来,表格显示数据以及鼠标触摸后气泡弹出层提示信息都是从后端传过来,实现动态表格的组件!!实现效果如下: 接口标准数据格式如下: {"data": {"date": ["8.20","8.21","…

Cmd终端

组策略停止更新 windows用户的分类 system&#xff08;系统用户&#xff09; administrator&#xff08;管理员用户&#xff09; 普通用户 访客用户 网络管理类命令练习 ping&#xff1a;用于测试网络连接是否正常。通过发送ICMP&#xff08;Internet Control Message Protoco…

力扣 | 递归 | 区间上的动态规划 | 486. 预测赢家

文章目录 一、递归二、区间动态规划 LeetCode&#xff1a;486. 预测赢家 一、递归 注意到本题数据范围为 1 < n < 20 1<n<20 1<n<20&#xff0c;因此可以使用递归枚举选择方式&#xff0c;时间复杂度为 2 20 1024 ∗ 1024 1048576 1.05 1 0 6 2^{20…

Linux--目录与文件操作函数

一、目录和&#xff08;硬&#xff09;链接 可在 shell 中利用 ln 命令为一个业已存在的文件创建新的硬链接 添加图片注释&#xff0c;不超过 140 字&#xff08;可选&#xff09; 2. 同一文件的所有名字&#xff08;链接&#xff09;地位平等—没有一个名字&#xff08;比如…

计应8-01-作业1-静态网页

IP C:\Users\WL>ipconfig // win 查看 ip Windows IP 配置以太网适配器 以太网: //连接特定的 DNS 后缀 . . . . . . . :本地链接 IPv6 地址. . . . . . . . : fe80::6c95:9da6:140c:c59e%13IPv4 地址 . . . . . . . . . . . . : 192.168.51.243//子网掩码 . . . .…

mysql阿拉伯数字转换中文数字函数

函数如下 1.中间一部分代码可以提取出来作为公共方法&#xff0c;我这里并没有提取&#xff0c;因为我是在代码中动态添加的 2.样式目前只做了&#xff1a;123转为一百二十三这类的 drop function if EXISTS zz_convert_number_chinese; create FUNCTION zz_convert_number_…

ELK系列之四---如何通过Filebeat和Logstash优化K8S集群的日志收集和展示

前 言 上一篇文章《日志不再乱: 如何使用Logstash进行高效日志收集与存储》介绍了使用ELK收集通用应用的日志&#xff0c;在目前大多应用都已运行在K8S集群上的环境&#xff0c;需要考虑怎么收集K8S上的日志&#xff0c;本篇就介绍一下如何使用现有的ELK平台收集K8S集群上POD的…

新型供应链攻击手法 — “Revival Hijack”

JFrog 的网络安全研究人员发现了一种名为“Revival Hijack”的新型 PyPI 攻击技术&#xff0c;该技术利用包删除策略绕过安全检查。据统计&#xff0c;超过 22,000 个程序包处于风险之中&#xff0c;可能会影响数十万名用户。 JFrog 的网络安全研究人员发现了一种用于攻击 Pyth…

易灵思时钟输出问题记录

在添加 GPIO时&#xff0c;设置Mode为clkout,并在output Clock中输入时钟名。 这里需要 注意的是&#xff0c; 1. 时钟名不能从core直接输出&#xff0c;而只能使用interface中使用的时钟&#xff0c;如PLL输出的时钟或者GCLK输入的时钟。 2. 易灵思输出时钟不能做其他用途&a…

2024中国产业园区运营商50强榜单揭晓:行业洗牌加速,数智化是关键!

近日&#xff0c;备受瞩目的“2024年度中国产业园区运营商50强”榜单正式揭晓&#xff0c;不仅照亮了行业内的领军之星&#xff0c;更为我们揭示了产业园区运营管理平台在推动经济转型升级中的关键力量与未来趋势的璀璨图景。 从以上产业园区运营商 50 强的角度来看&#xff0…

30岁程序员的焦虑:转行还是继续死磕?现在什么方向更有前景?

最适合转入AI大模型的莫过于程序员和在读大学生了吧。 对于程序员来说&#xff0c;码农之路并不是一帆风顺。对于每一个入行IT业的社会青年来说&#xff0c;谁不是抱着想要成为最高峰的技术大咖或者跃进管理岗的小目标&#xff1f; 然而往往更多的人并非互联网吹捧的如此耀眼…

云原生技术:‌引领数字化转型的新浪潮

云原生技术&#xff1a;‌引领数字化转型的新浪潮 在数字化转型的时代背景下&#xff0c;‌企业面临着前所未有的挑战与机遇。‌随着云计算技术的飞速发展&#xff0c;‌云原生技术作为一种新型的应用程序开发和部署方式&#xff0c;‌正逐步成为构建高可用、‌可扩展应用程序…

MySQL复习1

基本概念 OLTP OLTP&#xff08;On-Line transaction processing&#xff09;翻译为联机事物处理&#xff1b;主要对数据库增删改查。 OLTP 主要用来记录某类业务事件的发生&#xff1b;数据会以增删改查的方式在数据库中更新处理操作&#xff0c;要求实施性强&#xff0c;稳…

OS_程序的装入与链接

2024.09.05&#xff1a;操作系统程序的装入与链接学习笔记 第12节 程序的装入与链接 2.1 程序的装入2.1.1 绝对装入方式2.1.2 可重定位装入方式&#xff08;静态重定位&#xff09;2.1.3 动态运行时装入方式&#xff08;动态重定位&#xff09; 2.2 程序的链接2.2.1 静态链接方…

LIN总线CAPL函数—— 检查LIN报头的时间(ChkStart_LINHeaderToleranceViolation

&#x1f345; 我是蚂蚁小兵&#xff0c;专注于车载诊断领域&#xff0c;尤其擅长于对CANoe工具的使用&#x1f345; 寻找组织 &#xff0c;答疑解惑&#xff0c;摸鱼聊天&#xff0c;博客源码&#xff0c;点击加入&#x1f449;【相亲相爱一家人】&#x1f345; 玩转CANoe&…

高级算法设计与分析 学习笔记3 哈希表

首先我们要讨论一个把n个数据放到列表S里面的问题&#xff1a; 但很显然&#xff0c;这些数据的范围有多大这个T就得有多大&#xff0c;而实际上要放的数字可能就几个&#xff08;比如就放一个1和一个10000000&#xff0c;那我还是要准备一个巨大的T&#xff09;&#xff0c;不…

【STM32】cubemx配置GPIO

直接使用STM32CubeMX点灯 使用之前的工程 配置GPIO 对四个灯设置GPIO输出 close后直接打开keil 演示

基于LangChain+LLM的相关技术研究及初步实践

0 1 概述 大模型概述 大模型是指具有大规模参数和复杂计算结构的机器学习模型。这些模型通常由深度神经网络构建而成&#xff0c;拥有数十亿甚至数千亿个参数。大模型的设计目的是为了提高模型的表达能力和预测性能&#xff0c;能够处理更加复杂的任务和数据。大模型在各种领…