Java-数据结构-栈和队列-Stack和Queue (o゚▽゚)o

news2024/11/22 21:24:39

文本目录:

❄️一、栈(Stack):

    ▶ 1、栈的概念:

  ▶ 2、栈的使用和自实现:

     ☑ 1)、Stack():

      ☑ 2)、push(E e):

     ☑ 3)、empty(): 

       ☑ 4)、peek(E e): 

      ☑ 5)、pop(E e): 

     ☑ 6)、size(E e): 

▶ 3、栈自实现的总代码:

❄️二、队列(Queue):

      ▶ 1、栈的概念:

▶ 2、队列的使用和自实现: 

      ☑ 1)、Queue():

       ☑ 2)、isEmpty():

     ☑ 3)、size():

     ☑ 4)、offer(E e):

     ☑ 5)、peek():

      ☑ 6)、poll():

▶ 3、队列的自实现的总代码:

❄️三、循环队列:

▶ 1、成员变量和初始化:

▶ 2、isEmpty()方法:

▶ 3、enQueue(int value)方法:、

 ▶ 3、isEmpty()方法:

 ▶ 4、deQueue()方法:

  ▶ 5、Front()方法:

  ▶ 6、Rear()方法:

❄️四、双端队列:

 ❄️五、总结:


❄️一、栈(Stack):

    1、栈的概念:

         栈:是一种特殊的线性表,其 只允需在固定的一端进行插入和删除操作

   进行插入和删除的一端叫做栈顶,另一端叫做栈底。并且要遵循 先进后出 的规则

压栈:栈的插入操作叫做压栈,入数据在栈顶。

出栈:栈的删除操作叫做出栈,出数据在栈顶。

我们来看看图片是怎样进行的:


  ▶ 2、栈的使用和自实现:

         我们来自实现一个栈,并且和 Java 自带的栈的方法进行比较,看看效果是否一样:

     ☑ 1)、Stack():

             构造一个空的栈。

这也是对于 栈 的构造方法,我们先来看看Java 中自带的是什么效果并且看看如何使用的:    这就是Java自带的栈的构造方法。

    我们接下来看看我们自己定义的栈是怎样写这个方法的,在写方法之前呢,我们先来把栈的成员变量来实现一下,我们对于栈呢,我们使用数组来存放数据

 我们来看看构造方法如何实现,这是个无参构造方法:

这个呢就是我们的自实现构造方法,我们来看看使用自实现的构造方法的效果:

所以效果是一样的。 


      ☑ 2)、push(E e):

             将 e 这个数据入栈。

 我们同样先来看看Java 中自带的是什么效果并且看看如何使用的:

 这就是 Java 里面自带的入栈操作。

         我们来看看自实现的push,在编写代码之前,我们先来看看 push 的思路是什么:

         我们的 push 呢,就是每次往数组下标指向的那个里面放数据,这个下标呢就是我们的 usedSize 这个下标,之后我们放入元素之后,我们要把 usedSize 这个长度往后加1。

         但是这里插入元素的时候呢,我们要注意,当我们的数组的内存满了的话,我们是不是要2倍扩容,所以我们要注意这一点:

对于 push 方法呢就是这个意思了。 我们来看看代码是如何实现的:

我们来看看使用效果如何:

 我们可以看到结果是一样的对于数据的存放。说明我们对于 push 这个方法是没有问题的。


     ☑ 3)、empty(): 

             判断栈是否为空。

这个方法就非常简单了,我们之间来看看Java 的和自实现的比较是否结果一样:

    当我们一开始创建栈的之后呢,判断栈是否为空的话,肯定是为空的所以返回 true 是正确的。由此可得我们的自定义的 empty() 代码是没有问题的。 


       ☑ 4)、peek(E e): 

              返回栈顶的元素,但是不出栈顶的元素。

我们也是来看看如何实现的: 

     这个代码也是很简单的,我们至于要返回 usedSize-1 的这个下标的元素就可以了,因为我们的usedSize总是比下标长 1 个单位

      但是这里我们也是需要注意的是,我们需要先判断一下,我们的栈是否为空,如果为空,都没有元素,所以返回不了元素。这也是 为什么我要先写 empty 这个方法的原因

    我们先来看代码,之后再看看Java中的和自实现的有没有区别:

运行的比较: 


      ☑ 5)、pop(E e): 

                  出栈顶的元素,并且把栈顶的元素删除。

      这个呢,我们先把栈顶的元素打印出来,之后呢我们把 usedSize 自减一次,使得我们访问不到删除的元素,这个比较简单,我们直接来看看代码:

我们来看看实现代码的比较:      我们可以看到我们最先访问的 23 这个栈顶,这个方法是pop,所以会把栈顶元素删除,之后我们再用peek 方法访问的是12,所以呢这个删除方法 peek 没有问题。


     ☑ 6)、size(E e): 

                返回栈的长度。

 这个方法是非常简单的,我们直接返回数组的有效的数组长度。我们直接看代码的实现吧:


▶ 3、栈自实现的总代码:

 OK,我们呢对于栈的方法的实现现在常用的都自实现完事了,我们现在来看看总代码:

public class MyStack {
    public int[] elem;//存放栈的数据
    public int usedSize;//我们数组的有效长度

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

    private boolean isFull() {
        return usedSize == elem.length;
    }
    public void push(int e) {
        if (isFull()) {
            //二倍扩容
            this.elem = Arrays.copyOf(elem,
                    2*elem.length);
        }
        //这是在放完元素后再自加
        elem[usedSize++] = e;
    }

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

    public int peek() {
        if (empty()) {
            System.out.println("栈为空没有元素");
            return -1;
        }

        return elem[usedSize - 1];
    }

    public int pop() {
        int e = peek();
        usedSize--;
        return e;
    }

    public int size() {
        return usedSize;
    }
}

   OK,我们对于栈的实现就已经完事了,我们开看看一道关于栈的选择题来看看吧: 

练习:

     我们来看看这道题选什么? 这道题呢,我们正确的呢是选择 C 因为C中呢我们出 3 后栈里的元素为2,1 从栈顶到栈底,所以我们不可能出1,在不先出2的情况下,所以C 是错误的。

   你是否选择正确了呢?


❄️二、队列(Queue):

    在了解队列之前呢,我们请出我们的那个数据结构的那个表单:

       我们要学习的 Queue 和我们之后要了解的 Deque 我们之前学习过的 LinkedList 这个类中都将它们实现了,所以呢我们的 LinkedList 类呢有 Queue 和 Deque 的性质。所以呢,LinkedList可以使链表、可以是队列(Queue)、可以是双端队列(Deque)

      ▶ 1、栈的概念:

       队列:是一种只允许一端进行插入元素,在另一端进行删除元素的特殊的线性表。

       队列具有 先进先出 的性质:进行插入的一端叫做队尾,进行删除的一端叫做队头。也就是队尾进,队头出。

       队列呢就相当于是我们 排队打饭 的例子,我们先来打饭的先走,后打饭的后走。

 我们来看看流程的表:

相当于这样:


▶ 2、队列的使用和自实现: 

      ☑ 1)、Queue():

      这里我们创建队列的时候要注意了,我们的 队列只是一个接口,不是类,所以不能创建对象,所以我们需要使用 LinkedList 类来进行创建,进行向上转型

我们来看看这个队列要如何创建:

   这个就是用 LinkedList 来进行来创建 队列 的方法。


        在我们自实现方法之前呢,我们来想一下,我们的队列使用什么结构来进行存储元素呢?

        我们在之前呢,我们了解到了 顺序存储 和 链式存储 两种方式,对于我们队列呢我们使用   链式存储 的方式来进行存储元素,但是我们 链式存储 有 单链表 和 双链表 两种方式,我们呢最好使用 双链表 的形式,这样呢方便我们 存储和删除,而且我们的队列要有头和尾,所以双链表更加的合适。这样呢我们了解队列怎样存储之后,我们来看看自实现队列:


       ☑ 2)、isEmpty():

               判断队列是否为空。

     这个方法是非常简单的,我们只需要判断 队头 是不是空就可以了或者我们判断一下有效长度是不是 0 也是可以判断的,因为我们每次出元素都在队头,当我们的头为空说明没有元素了。我们来看看代码:

  这个呢,我们就不进行演示了,我们直接继续往下看: 


     ☑ 3)、size():

           返回队列的长度。

    我们再来看一个简单的代码,这个代码就非常简单了,我们不是定义了一个 usedSize 这个成员变量了吗,这个就是我们队列的有效长度,所以我们直接返回这个 usedSize 这个成员变量就可以了,我们来看看代码的实现:

是不是很简单呢,所以我们这个也不进行代码的演示了,我们还是继续往下看: 


     ☑ 4)、offer(E e):

           入队列操作。

      对于入队的之前呢,我们要先进行对队列的判断,如果我们的队列是空的话,我们要把我们的要入队的节点newNode,我们要执行 firast = last = newNode 的操作

       第一步,当我们的队列不为空的时候呢,我们要把 last.next 指向 newNode 这个节点。

       第二步,我们把新的节点 newNode.prev 指向我们的last这个节点,

       第三步,把 last 往后移一位。

这个呢,就是我们入队的操作思路啦,之后我们,来看看代码是如何实现的: 

     这个呢就是我们的入队操作了,我们来看看 Java 中的队列和自实现的队列的 入队 操作有没有不同的。 

我们可以看到,我们的自实现是没有问题的。Ok,我们来看下一个 队列 的操作:


     ☑ 5)、peek():

          获得队头的元素

   对于这个方法呢,是非常的简单的,我们想要队头的元素的话,我们只需要返回 first.val 这个数据就可以了:

比如这个呢,我们的队头元素就是 first.val 这个元素 ,所以我们来看看代码:

看一下运行的结果怎么样: 

OK,我们可以看到这个方法是没有问题的,我们接下来看看 队列 的最后一个常用的方法:


      ☑ 6)、poll():

            出队列操作。

       我们对于出队列之前呢,我们要先把队列判断一下是否为空,之后我们才能进行出队操作。 

       对于出队操作呢,我们是出队头的元素,我们呢要先把队头元素出出来,之后我们在把 first 往后移动一位,是我们出的那个元素,在队列中删除。但是呢,如果我们的 first 不是空的话,我们呢要把 first.prev 赋值为null,因为我们要把前一个节点删除,所以呢,我们要置空

       我们来看看方法的思路:

了解思路之后呢,我们来看看代码如何编写的:

 

 我们来看看代码有没有问题:

      我们可以看到当我们的 poll 执行之后呢,我们的 peek 的元素就变了,说明我们已经出队了,所以没有问题。


▶ 3、队列的自实现的总代码:

public class MyQueue {

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

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

    public ListNode first;//队头
    public ListNode last;//队尾
    public int usedSize;//长度

    public boolean isEmpty() {
        return first == null;
        //return usedSize == 0;
    }

    public int size() {
        return usedSize;
    }

    public void offer(int val) {
        ListNode newNode = new ListNode(val);

        if (isEmpty()) {
            first = last = newNode;
        }else {
            last.next = newNode;
            newNode.prev = last;
            last = last.next;
        }
        usedSize++;
    }

    public int poll() {
        if (isEmpty()) {
            return -1;
        }
        int val = first.val;
        first = first.next;

        if (first != null) {
            first.prev = null;
        }
        usedSize--;
        return val;
    }

    public int peek() {
        if (isEmpty()) {
            return -1;
        }
        return first.val;
    }
}

       我们的队列呢就到这里就结束了,接下来我们来看一个特殊的队列——循环队列。 


❄️三、循环队列:

 我们呢,先来了解一下循环队列长什么样的,是怎样进行循环的,我们来看看循环队列的形状:

 

    这个呢就是我们的循环队列了,它就像一个轮子一样,是一个环状的。就相当于我们把数组给卷起来似得。

     当这个队列是空的时候呢,我们的 front 和 rear 是在同一个位置,就是相等。

那么我们接下来看看这个的存储过程,并且当什么时候呢我们才能知道我们的空间是满的呢?

我们一个一个来解决:

          这样存放元素呢,我们满的话呢·,front 和 rear 是在一个位置上,但是我们在一个位置上的时候呢,我们是用来判断是否是空的情况下,所以呢,判满是不能这样判断的,那么我们用什么办法呢?我们呢,有三种方法来判断循环队列是否是满的

 1、定义size来判断

               当我们的队列的长度和size的长度相等的时候呢,我们就是满的。

 2、添加标记,用boolean来判断

              每当我们放元素的时候呢,我们把那个位置标记为 true 没有元素为 false,来判断是否满

 3、保留一个位置,浪费一个空间来进行判断

             就是当 rear 的下一个位置为 front 的时候呢,我们就是满的。比如这样:

 我们呢要如何才能判断 rear 的下一个是 front 呢? 是不是想到的是 rear + 1 =  front 就可以了呢?

    这个呢还是有点小瑕疵的,当我们的 rear 是 0 的时候我们的 front 为 1 的时候这种的是可以判断的,像这样:

   但是呢当我们的 rear 为 7 ,front 为 0 的时候就不对了,rear + 1 = 8 ≠ front ,那么我们要如何才能判断呢,我们呢这时候就有了一个公式:

              \left (rear + 1 \right )\varnothing len

比如我们 7 和 0 就是这样:(7 + 1) % 8 = 0

这个队列呢,也是一道题,我们来看链接

        循环队列


▶ 1、成员变量和初始化:

正确的代码: 


▶ 2、isEmpty()方法:

             判断是否是满的

 这里我们直接用公式:


▶ 3、enQueue(int value)方法:、

          入队操作

   这里呢,我们就是直接往 rear 下标进行放入元素,之后 rear 进行增加,但是这里我们不能使用rear++ 来进行增加,因为当我们的 rear 为7时候呢,不能++,那样就为8了,所以这里我们也要用公式来写


 ▶ 3、isEmpty()方法:

         判断队列是否为空

 这个比较简单,我们直接判断 rear 是否等于 front 就可以了。


 ▶ 4、deQueue()方法:

       出队操作

       对于这个方法,我们只需要把 front 这个下标往后走就可以了虽然我们没有删除元素,但是当我们再次在那个位置添加元素的时候,会把原先的数据覆盖掉但是这里我们的 front 的移动也需要使用公式来移动。来看代码:


  ▶ 5、Front()方法:

     得到队头元素

这个呢,我们直接返回 front 下标的元素即可 。


  ▶ 6、Rear()方法:

      得到队尾元素。

    这个方法呢,我们在对于队尾的位置判断上要麻烦一些,当我们 rear 在0下标的时候,队尾下标为7,但是呢,我们在 rear -1 的时候,和结果不一致,这里呢我们要判断,当 rear=0 的时候,我们的队尾下标为 elem.length- 1,其余时为 rear-1,我们来看代码:


我们的循环队列就到这里就结束了,我们再来看一种特殊的队列,叫——双端队列(Deque)

❄️四、双端队列:

    这个队列呢,我们不进行详细的讲解,我们了解一下其工作原理的图和其构造方法即可。和我们学习的队列差不多,只是增加了 头尾都可以进出 :

 之后我们来看一下其接口是实现:


 ❄️五、总结:

     OK,这次的关于呢 线性表中的 栈和队列 就都介绍完毕了,下次呢我们来练习一下它们的习题,这次就到这里就结束了,让我们期待下次的分享吧!!!拜拜~~~

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

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

相关文章

将添加功能的抽屉剥离,在父组件调用思路

一、新建组件 新建AddRoleEditerDrawer.vue<template><div><el-drawer v-model"dialog" title"添加角色" :before-close"handleClose" direction"rtl" colse"cancelForm"class"demo-drawer" moda…

基于UE5和ROS2的激光雷达+深度RGBD相机小车的仿真指南(五):Blender锥桶建模

前言 本系列教程旨在使用UE5配置一个具备激光雷达深度摄像机的仿真小车&#xff0c;并使用通过跨平台的方式进行ROS2和UE5仿真的通讯&#xff0c;达到小车自主导航的目的。本教程默认有ROS2导航及其gazebo仿真相关方面基础&#xff0c;Nav2相关的学习教程可以参考本人的其他博…

MQ-2烟雾传感器详解(STM32)

目录 一、介绍 二、传感器原理 1.原理图 2.引脚描述 3.工作原理介绍 三、程序设计 main.c文件 mq2.h文件 mq2.c文件 四、实验效果 五、资料获取 项目分享 一、介绍 MQ-2气体传感器是一种常用的气体传感器&#xff0c;用于检测空气中的烟雾浓度。工作原理是基于半导…

App Store最低版本要求汇总

1&#xff0c;自此日期起&#xff1a; 2024 年 4 月 29 日 自 2024 年 4 月 29 日起&#xff0c;上传到 App Store Connect 的 App 必须是使用 Xcode 15 为 iOS 17、iPadOS 17、Apple tvOS 17 或 watchOS 10 构建的 App。将 iOS App 提交至 App Store - Apple Developer 2&…

天然药物化学史话:“四大光谱”在天然产物结构鉴定中的应用-文献精读46

天然药物化学史话&#xff1a;“四大光谱”在天然产物结构鉴定中的应用&#xff0c;天然产物化学及其生物合成必备基础知识~ 摘要 天然产物化学研究在药物研发中起着非常重要的作用&#xff0c;结构研究又是天然产物化学研究中最重要的工作之一。在天然药物化学史话系列文章的…

Elasticsearch:无状态世界中的数据安全

作者&#xff1a;来自 Elastic Henning Andersen 在最近的博客文章中&#xff0c;我们宣布了支持 Elastic Cloud Serverless 产品的无状态架构。通过将持久性保证和复制卸载到对象存储&#xff08;例如 Amazon S3&#xff09;&#xff0c;我们获得了许多优势和简化。 从历史上…

科研绘图系列:R语言富集散点图(enrichment scatter plot)

介绍 富集通路散点图(Enrichment Pathway Scatter Plot)是一种数据可视化工具,用于展示基因集富集分析(Gene Set Enrichment Analysis, GSEA)的结果。 横坐标是对应基因名称,纵坐标是通路名称,图中的点表示该基因在某个通路下的qvalue,可以简单理解为不同环境下的贡献…

以后写代码都是AI自动写了,Cursor+Claude-3.5-Sonnet,Karpathy 点赞的 AI 代码神器。如何使用详细教程

Cursor 情况简介 AI 大神 Andrej Karpathy 都被震惊了&#xff01;他最近在试用 VS Code Cursor Claude Sonnet 3.5&#xff0c;结果发现这玩意儿比 GitHub Copilot 还好用&#xff01; Cursor 在短短时间内迅速成为程序员群体的顶流神器&#xff0c;其背后的原因在于其默认使…

AIGC批量处理文件系列:word、pdf文件改名

1.背景 大家应该也有遇到&#xff0c;自己电脑有很多文件命名不合理的文件&#xff0c;比如&#xff1a;文件1、想法3 &#xff0c;当你长时间再看到这个文件的时候&#xff0c;已经很难知道文件内容。 今天我们将借助AIGC的编码能力&#xff0c;帮我们生成一个批量改文件名的…

【H2O2|全栈】Markdown | Md 笔记到底如何使用?【前端 · HTML前置知识】

Markdown的一些杂谈 目录 Markdown的一些杂谈 前言 准备工作 认识.Md文件 为什么使用Md&#xff1f; 怎么使用Md&#xff1f; ​编辑 怎么看别人给我的Md文件&#xff1f; Md文件命令 切换模式 粗体、倾斜、下划线、删除线和荧光标记 分级标题 水平线 引用 无序…

哪种超声波清洗机效果好?较好的超声波眼镜清洗机品牌推荐

作为一名拥有20年戴镜经验的眼镜爱好者&#xff0c;我深深体会到眼镜清洁的挑战&#xff1a;微小缝隙里的污垢难以触及&#xff0c;频繁的脏污让我苦于找不到清洁时机&#xff0c;而用力不当的擦拭方法更是可能对眼镜特别是镜片造成伤害&#xff0c;这确实让人感到苦恼&#xf…

js 写个 最简单的 chrome 插件,修改网页背景颜色

起因(目的): 阅读电子书的时候&#xff0c; 网页背景太亮了&#xff0c;看久了眼睛难受。 最近看的书是: 金瓶梅 估计至少需要2个星期才能看完。 操作步骤: 新建一个 manifest.json 文件, 填入一些信息。 “manifest_version”: 3, # 2 已经被废弃了。新建图片文件夹&#x…

JVM - Java内存区域

文章目录 目录 文章目录 运行时数据区域 程序计数器 栈 Java虚拟机栈 本地方法栈 栈帧的组成 局部变量表 操作数栈 帧数据 堆 方法区 直接内存 总结 运行时数据区域 Java虚拟机在执行Java程序的过程中会把它所管理的内存区域划分为若干个不同的数据区域。这些区…

FPGA开发:初识FPGA × 开发环境

FPGA是什么&#xff1f; FPGA的全称是现场可编程门阵列&#xff08;Field Programmable Gate Array&#xff09;&#xff0c;一种以数字电路为主的集成芯片&#xff0c;属于可编程逻辑器件PLD的一种。简单来说&#xff0c;就是能用代码编程&#xff0c;直接修改FPGA芯片中数字…

Java+Selenium+ChromeDriver谷歌版环境搭建

1、创建测试项目 创建一个Maven项目即可 2、添加Selenium依赖 最好使用Selenium3版本 3、下载对应版本的ChromeDriver 找到自己浏览器对应的版本 下载ChromeDriver&#xff08;114版本以后的&#xff0c;114版之前的直接到官网下载&#xff09;下载地址 将下载好的驱动…

Windows下Python和PyCharm的应用(六)__应用Opencv的第一个程序(图片载入)

1、首先创建一个Pycharm工程 2、然后新建一个Python file 录入基本的内容&#xff1a; import cv2imgcv2.imread(pedal.jpg)#显示图片cv2.imshow(image,img)#等待按键cv2.waitKey(0)#结束显示&#xff0c;销毁窗口cv2.destroyAllWindows()#保存图片cv2.imwrite(example2.jpg,i…

解决 Ant Design Vue Upload 组件在苹果手机上只能拍照无法选择相册的问题

最近上线发现了这个问题&#xff0c;看别的文档改了很多属性也不行&#xff0c;发现element组件就可以&#xff0c;对比之后就知道问题所在。 原因&#xff1a; 默认情况下&#xff0c;iOS 设备会将 <input type"file"> 的 capture 属性设置为 true&#xff0…

三维激光扫描点云配准外业棋盘的布设与棋盘坐标测量

文章目录 一、棋盘标定板准备二、棋盘标定板布设三、棋盘标定板坐标测量一、棋盘标定板准备 三维激光扫描棋盘是用来校准和校正激光扫描仪的重要工具,主要用于提高扫描精度。棋盘标定板通常具有以下特点: 高对比度图案:通常是黑白相间的棋盘格,便于识别。已知尺寸:每个格…

【前端】animation动画以及利用vue制作简单的透明度改变动画,包含vue生命周期实现

一. 问题描述 想做一个文字透明度从1到0然后再从0到1的css动画。 二. 代码写法 2.1 animation写法 2.1.1 animation属性key 2.1.2 代码展示 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"…

芯片解决方案--SL8541e-OpenHarmony适配方案

摘要 本文描述8541E芯片适配OpenHarmony的整体方案。 本文描述的整体方案&#xff0c;不止适用于8541e&#xff0c;也适用于该芯片厂家的其他芯片&#xff0c;如7863、7885&#xff0c;少部分子系统会略有差异。 整体方案架构 整体方案架构如下图&#xff0c;遵循OpenHarmo…