数据结构 之 队列(Queue)

​​​​​​​

🎉欢迎大家观看AUGENSTERN_dc的文章(o゜▽゜)o☆✨✨

🎉感谢各位读者在百忙之中抽出时间来垂阅我的文章,我会尽我所能向的大家分享我的知识和经验📖

🎉希望我们在一篇篇的文章中能够共同进步!!!

🌈个人主页:AUGENSTERN_dc

🔥个人专栏:C语言 | Java | 数据结构

⭐个人格言:

一重山有一重山的错落,我有我的平仄

一笔锋有一笔锋的着墨,我有我的舍得

目录

1. 定义:

2. 队列的常用方法和模拟实现:

2.1 常用方法:

2.2 模拟实现:

 3. 队列的模拟实现源码:

4. 循环队列

4.1 模拟实现:

5. 双端队列:


1. 定义:

队列和栈类似,是一种只允许在一端进行插入数据操作,在另一端进行删除数据操作的特殊线性表;

进入队列的一端称为队尾,离开队列的一端称为队头

队列这个结构遵循先进先出的原则;

 在日常生活中,例如:

多人在网上对老师提交任务时,会将我们所提交的任务存放到一个队列中,然后队列将这些任务按照先进先出的顺序进行出队和入队的操作,老师看到的任务,也就会按照提交时间的先后来排序;
 

由上图可以看出Queue是一个接口,底层是由链表(LinkedList)实现的;

2. 队列的常用方法和模拟实现:

2.1 常用方法:

方法作用
offer(E e)将e进行入队操作
E poll()

将e进行出队列操作,并且返回e的值

E peek()获取队头元素
int size()获取队列的长度
boolean isEmpty()判断队列是否为空

(在队列的模拟实现中,我们并不使用泛型,而是使用整形来代替泛型) 

以上就是队列的常用方法,接下来我们进行模拟实现:

2.2 模拟实现:

队列的底层是由链表来实现的,我们先创建一个My_Queue类:

public class My_Queue {
    public static class ListNode {
        ListNode next;      //节点的后继
        ListNode prev;      //节点的前驱
        int value;          //节点的值

        public ListNode() {
            //不带参数的构造方法
        }
        public ListNode(int value){
            //带一个参数的构造方法,将节点的值赋为value
            this.value = value;
        }
    }

    ListNode first;         //队头节点
    ListNode last;          //队尾节点
    int size = 0;           //队列长度
}

< 1 > offer方法:

offer方法是将指定元素插入到队列的队尾:

与之前的栈和顺序表不同,由于队列的底层是用链表实现的,故不需要判断队列是否满了;

// 入队列---向双向链表位置插入新节点
    public void offer(int e){
        ListNode newNode = new ListNode(e);     //实例化一个节点
        if(first == null){                      //若该队列为空
            first = newNode;                    //将队头和队尾都更新为newNode
            last = newNode;
        }else{                                  //若队列不为空
            last.next = newNode;                //将newNode赋值给队尾.next
            newNode.prev = last;                //将newNode的pre赋值为队尾
            last = newNode;                     //将队尾更新为newNode
        }
        last = newNode;                         //更新队尾
        size++;                                 //队列长度 +1
}

< 2 > poll方法:

poll方法是将队头的元素进行出队操作,并返回队头元素的值:

在进行该操作之前,我们需要判断队列是否为空,若为空,则需抛出异常:

异常代码如下:

public class QueueEmptyException extends RuntimeException {
    public QueueEmptyException () {
        super();
    }

    public QueueEmptyException (String str) {
        super(str);
    }
}

poll方法如下:

public int poll(){
        // 1. 队列为空
        // 2. 队列中只有一个元素----链表中只有一个节点---直接删除
        // 3. 队列中有多个元素---链表中有多个节点----将第一个节点删除
        int value = 0;
        if(first == null){      //若为空,则抛出异常
            throw new QueueEmptyException("队列为空,不能进行poll操作!!!");
        }else if(first == last){        //若只有一个节点,则直接删除该节点
            last = null;
            first = null;
        }else{
            value = first.value;        //将队头的元素赋值给value
            first = first.next;         //将队头更新为队头的下一个节点
            first.prev.next = null;
            first.prev = null;
        }
        size--;                         //将队列长度 -1
        return value;                   //返回队头的值
}

< 3 > peek方法:

peek方法是返回队头的节点的值:

// 获取队头元素---获取链表中第一个节点的值域
    public int peek(){
        if(first == null){      //若队列为空,则抛出异常
            throw new QueueEmptyException("队列为空,不能进行peek操作!!!");
        }
        return first.value;     //返回队头的值
}

< 4 > size方法:

size方法是返回队列的长度:

public int size() {
        return size;        //返回队列的长度
}

< 5 > isEmpty方法:

isEmpty是判断队列是否为空:

public boolean isEmpty(){
        return first == null;       //返回队头是否为空 的值
}

 3. 队列的模拟实现源码:

public class My_Queue {
    public static class ListNode {
        ListNode next;      //节点的后继
        ListNode prev;      //节点的前驱
        int value;          //节点的值

        public ListNode() {
            //不带参数的构造方法
        }
        public ListNode(int value){
            //带一个参数的构造方法,将节点的值赋为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;                    //将队头和队尾都更新为newNode
            last = newNode;
        }else{                                  //若队列不为空
            last.next = newNode;                //将newNode赋值给队尾.next
            newNode.prev = last;                //将newNode的pre赋值为队尾
            last = newNode;                     //将队尾更新为newNode
        }
        last = newNode;                         //更新队尾
        size++;                                 //队列长度 +1
    }

    // 出队列---将双向链表第一个节点删除掉
    public int poll(){
        // 1. 队列为空
        // 2. 队列中只有一个元素----链表中只有一个节点---直接删除
        // 3. 队列中有多个元素---链表中有多个节点----将第一个节点删除
        int value = 0;
        if(first == null){      //若为空,则抛出异常
            throw new QueueEmptyException("队列为空,不能进行poll操作!!!");
        }else if(first == last){        //若只有一个节点,则直接删除该节点
            last = null;
            first = null;
        }else{
            value = first.value;        //将队头的元素赋值给value
            first = first.next;         //将队头更新为队头的下一个节点
            first.prev.next = null;
            first.prev = null;
        }
        size--;                         //将队列长度 -1
        return value;                   //返回队头的值
    }

    // 获取队头元素---获取链表中第一个节点的值域
    public int peek(){
        if(first == null){      //若队列为空,则抛出异常
            throw new QueueEmptyException("队列为空,不能进行peek操作!!!");
        }
        return first.value;     //返回队头的值
    }

    public int size() {
        return size;        //返回队列的长度
    }

    public boolean isEmpty(){
        return first == null;       //返回队头是否为空 的值
    }
}

4. 循环队列

实际中我们有时还会使用一种队列叫循环队列。如操作系统课程讲解生产者消费者模型时可以就会使用循环队列。 环形队列通常使用数组实现。

4.1 模拟实现:

/*
    解题思路:
    1. 注意,循环队列底层空间大小是固定的
    2. 采用计数方式实现队列空或者满的判断
    3. 入队列时:队列可能满,往队尾插入,注意back在末尾特殊情况
    4. 出队列时:队列可能空,删除队头元素,注意front可能在队尾
    5. 获取队头注意空队列时返回-1
    6. 获取队尾时,注意back-1可能为负数,队尾元素下标:
       (back-1+array.length)%array.length
*/
class MyCircularQueue {
    int[] array;
    int front;   // 队头
    int back;    // 队尾
    int count;   // 队列中有效元素个数
    public MyCircularQueue(int k) {
        array = new int[k];
    }
    
    public boolean enQueue(int value) {
        if(isFull()){
            return false;
        }

        // 在队尾插入一个元素,然后back往后移动
        array[back] = value;
        back++;

        // back往后移动之后,可能会来到空间末尾
        // 此时将back挪到空间起始位置
        if(back == array.length){
            back = 0;
        }

        count++;
        return true;
    }
    
    public boolean deQueue() {
        if(isEmpty()){
            return false;
        }

        // 出队列,队头往后移动
        ++front;

        // 队头往后移动之后也可能会来到空间末尾
        // 此时需要挪到空间起始位置
        front %= array.length;
        --count;
        return true;
    }
    
    public int Front() {
        if(isEmpty()){
            return -1;
        }

        // 如果队列不空,说明队列中有元素,队头元素直接返回front即可
        return array[front];
    }
    
    public int Rear() {
        if(isEmpty()){
            return -1;
        }

        // 如果队列不空,说明队列中有元素
        // 队尾元素即:back-1,
        // 如果back不在0号位置,back-1就是队尾元素下标
        // 如果back在0号位置,-1之后就是负数,因此需要+数组长度
        // 两个结合起来:
        return array[(back - 1 + array.length)%array.length];
    }
    
    public boolean isEmpty() {
        return 0 == count;
    }
    
    public boolean isFull() {
        return count == array.length;
    }
}

5. 双端队列:

双端队列(deque)是指允许两端都可以进行入队和出队操作的队列,deque 是 “double ended queue” 的简称。 那就说明元素可以从队头出队和入队,也可以从队尾出队和入队。

Deque是一个接口,使用时必须创建LinkedList的对象。

以上就是队列的全部内容:感谢观看!!!!

制作不易,三连支持

谢谢!!!

以上的模拟实现代码未必是最优解,仅代表本人的思路,望多多理解,谢谢!!

最后送给大家一句话,同时也是对我自己的勉励:

知不足而奋进,望远山而前行!!!!

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

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

相关文章

数据结构知识点汇总(持续更新版)

数据结构 一、绪论 检测知识&#xff1a; 1.1基本概念 以前的计算机 弹道计算机 现如今 主要运用于非数值的计算 基本概念和术语 数据&#xff1a;是信息的载体&#xff0c;描述客观事物属性的值&#xff0c;字符以及所有能输入到计算机中并被计算机程序识别和处理的符号的…

vite打包流程和原理

文章目录 打包原理Vite比Webpack快&#xff1f;在生产环境下的表现启动项目后&#xff0c;完成加载比较慢&#xff1f;Esbuild & Rollup热更新 打包原理 vite利用了ES module这个特性&#xff0c;使用vite运行项目时&#xff0c;首先会用esbuild进行预构建&#xff0c;将所…

Java 根据IP获取IP地址信息(离线)

<!-- https://mvnrepository.com/artifact/org.lionsoul/ip2region --><dependency><groupId>org.lionsoul</groupId><artifactId>ip2region</artifactId><version>2.7.0</version></dependency> 地址&#xff1a;http…

影响交易收益的因素有哪些?

在尝试做交易时&#xff0c;你可能会问自己一个问题&#xff1a;交易一天能赚多少钱&#xff1f;“如果我全职投入交易&#xff0c;一天能赚多少&#xff1f;”或者更广泛地说&#xff0c;“交易能为我带来怎样的财富&#xff1f;”这些问题本质上都充满了不确定性&#xff0c;…

PCM和I2S区别

I2S和PCM接口都是数字音频接口&#xff0c;而所见的蓝牙到cpu以及codec的音频接口都是用PCM接口&#xff0c;是不是两个接口有各自不同的应用呢&#xff1f;先来看下概念。 PCM&#xff08;PCM-clock、PCM-sync、PCM-in、PCM-out&#xff09;脉冲编码调制&#xff0c;模拟语音信…

力扣L12--- 125验证回文串(java版)-2024年3月15日

1.题目 2.知识点 注1&#xff1a;在 Java 中&#xff0c;toString() 方法用于将对象转换为字符串表示形式。对于数组对象&#xff0c;toString() 方法将返回数组的字符串表示形式&#xff0c;其中包含数组中每个元素的字符串表示形式&#xff0c;以逗号分隔&#xff0c;并且包…

使用IDEA2023创建传统的JavaWeb项目并运行与调试

日期:2024-0312 作者:dusuanyun 文档环境说明: OS:Deepin 20.9(Linux) JDK: OpenJDK21 Tomcat:10.1.19 IDEA: 2023.3.4 (Ultimate Edition) 本文档默认已经安装JDK及环境变量的配置。 关键词…

【RPG Maker MV 仿新仙剑 战斗场景UI (四)】

RPG Maker MV 仿新仙剑 战斗场景UI 四 三级战斗指令菜单效果代码完成效果 下篇预告 三级战斗指令菜单 仙剑1中三级战斗的菜单内容如下&#xff1a;使用、投掷、装备这三项。 效果 在RMMV中原始菜单中是没有这三级菜单的&#xff0c;因此需要重新进行添加进去。 代码 这里贴…

量子遗传算法优化VMD参数,五种适应度函数任意切换,最小包络熵、样本熵、信息熵、排列熵、排列熵/互信息熵...

关于量子遗传算法&#xff0c;在众多文献均有应用。下面简述一下原理。 &#xff08;1&#xff09;量子比特编码 子遗传算法通过引入量子比特来完成基因的存储和表达。量子比特是量子信息中的概念&#xff0c;它与经典比特不同&#xff0c;是因为它可以在同一时刻处于两个状态的…

Leet code 438 找到字符串中所有字母异位词

解题思路&#xff1a;滑动窗口 三步走 进窗口 判断 出窗口 然后更新结果 定义两个hash表在第一个表中存 p的有效字符 比如 abc a一个 b一个 c一个 这样就存在三个有效字符 在第二个hash表中进行滑动窗口的运行 定义一个常量count 如果滑动窗口中有效字符存在一个就…

string模拟实现

前言 上一期我们对STL进行了简单的介绍以及学习了string常用API的基本使用&#xff01;本期我们来探索它的底层实现&#xff01;自己对string的常用的接口进行模拟实现&#xff01; 本期内容介绍 常用成员函数模拟实现 常用非成员函数模拟实现 成员函数 构造函数 在进行模拟…

计算机网络 谢希仁(001-2)

计算机网络-方老师 总时长 24:45:00 共50个视频&#xff0c;6个模块 此文章包含1.5到1.7的内容 1.5计算机网络类别 连通 共享 分类方法 广域网是边缘部分和核心部分的核心部分 以前是拨号连接 现在是光纤 总线型 星型 环形网 1.6计算机网络的性能 带上单位之后就不是…

git bash 命令行反应慢、卡顿(定位出根本原因)

参考该博主&#xff1a; https://blog.csdn.net/weixin_50212044/article/details/131575987?utm_mediumdistribute.pc_relevant.none-task-blog-2defaultbaidujs_baidulandingword~default-0-131575987-blog-130024908.235v43pc_blog_bottom_relevance_base4&spm1001.210…

IP证书有什么作用?怎么申请?

关于IP地址证书&#xff0c;它的主要作用有这么几个点&#xff1a; 1.验明正身&#xff1a;就像身份证一样&#xff0c;它可以证明某个服务器的IP地址是真的、合法的&#xff0c;让咱知道咱们连接的就是正确的服务器&#xff0c;而不是冒牌货。这样一来&#xff0c;就可以降低像…

使用OpenCV实现人脸特征点检测与实时表情识别

引言&#xff1a; 本文介绍了如何利用OpenCV库实现人脸特征点检测&#xff0c;并进一步实现实时表情识别的案例。首先&#xff0c;通过OpenCV的Dlib库进行人脸特征点的定位&#xff0c;然后基于特征点的变化来识别不同的表情。这种方法不仅准确度高&#xff0c;而且实时性好&am…

塑料工厂5G智能制造数字孪生可视化平台,推进塑料行业数字化转型

塑料工厂5G智能制造数字孪生可视化平台&#xff0c;推进塑料行业数字化转型。塑料制造行业作为重要的工业领域&#xff0c;亟需借助这一平台实现产业升级与转型&#xff0c;以适应市场的变化和提高生产效率。传统的塑料制造过程往往存在生产效率低下、资源浪费、环境污染等问题…

鸿蒙车载原生开发,拓展新版图

一天内连发“五弹”、HiCar 4.0首次上车 华为鸿蒙狂扩“汽车朋友圈”-上游新闻 汇聚向上的力量 3月15日&#xff0c;在“华为云&华为终端云服务创新峰会2024”上&#xff0c;华为首批汽车行业伙伴广汽传祺、岚图汽车、零跑汽车、凯翼汽车加入鸿蒙生态合作&#xff0c;华为…

Python - 应用篇 :ChatGPT +Pycharm 序列号自动生成

前言&#xff1a; 客户要求在产品外壳上新增可追溯的二维码贴花&#xff0c;二维码信息内容如下&#xff1a; 编码格式&#xff1a;SBD 零部件代码 控制盒序列号 控制盒厂家 例如&#xff1a;[)>06P725-18428S24031410001ZJL SBD 零部件代码&#xff1a;[)>06P725-184…

考研复习C语言进阶(3)

结构体 1 结构体的声明 1.1 结构的基础知识 结构是一些值的集合&#xff0c;这些值称为成员变量。结构的每个成员可以是不同类型的变量。 1.2 结构的声明 struct tag { member-list; }variable-list; 例如描述一个学生&#xff1a; struct Stu { char name[20];//名字 int ag…

java-ssm-jsp-基于java的客户管理系统的设计与实现

java-ssm-jsp-基于java的客户管理系统的设计与实现 获取源码——》公主号&#xff1a;计算机专业毕设大全