【数据结构】队列(Queue)

devtools/2024/10/20 7:17:01/

目录

队列概念

​方法

队列模拟实现

链表实现队列

入队列

出队列

获取队头元素

数组实现队列

入队列

出队列

返回头队列

返回尾队列

完整代码

双链表实现队列

数组实现队列(设计循环队列)


队列概念

队列:只允许在一段进行插入数据操作,在另一端进行删除数据操作的特殊线性表

队列具有先进先出的特点,就像是排队一样,先排队的先出去。

入队列:进行插入操作的一段称为队尾。

出队列:进行删除操作的一段称为队头。

方法

方法功能
boolean offer(E e)入队列
E poll()出队列
peek()获取队头元素
int size()获取队列中有效元素个数
boolean isEmpty()检测队列是否为空

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

队列模拟实现

队列可以通过链表和数组实现

链表实现队列

这里实现队列采用的双向链表,所以定义一些基本变量如下,useSize记录队列中数据个数。

java">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 = null; //队头public ListNode last = null;  //队尾public int useSize = 0;
}
入队列

offer方法

在往链表中放数据时,要考虑链表是否为空,当链表为空,队头和队尾都等于这个数据。

这时可以写一个isEmpty方法来判断,对于判断是否为空的条件,可以看useSize是否为0,也可以时first是否为0。

java">    public boolean isEmpty(){return useSize == 0;//return first == 0;}

当链表不为空时,这时实现的是尾插,所以offer方法完整部分为:

java">    public void offer(int val){ListNode node = new ListNode(val);if(isEmpty()){first = last = node;}else{last.next = node;node.prev = last;last = last.next;}useSize++;}
出队列

poll方法
出队列时也要考虑是否为空,用链表实现出队列要做的是把头节点往后挪一个位置。

当链表中只有一个节点,就没有必要再空置前一个结点了。

java">    public int poll(){if(isEmpty()){return -1;}int val = first.val;first = first.next;//一个节点,就没必要再置空前一个节点if(first != null){first.prev = null;}useSize--;return val;}
获取队头元素

peek方法

获取队头元素思路很清晰,只要返回first对应的值即可。也要进行是否为空的判断。

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

数组实现队列

这里主要做得是:设计循环队列,我们可以把循环队列设想成一个环,在一个有限的环里实现队列。设定front为头位置,rear为尾位置。

 判断数组是否为满有三种方法:

  1. 定义size
  2. 添加标记 定义boolean类型
  3. 浪费一个空间,即:确保一个空间里面不放元素,判断:rear下一个是不是front

这里我们采用的是最后一种方法:浪费一个空间。

不过还要解决一个问题: rear或者front 下标如何从 7位置 到 0位置?

对应的解决方案为:(rear +1)% 数组长度,front同理。

因为采用数组来实现循环队列,所以第一步是定义基础变量。

java">class MyCircularQueue {public int front;public int rear;public int[] elem;public MyCircularQueue(int k) {this.elem = new int[k+1];}
}

因为需要浪费一个位置,所以申请 k+1个位置。 

入队列

enQueue方法

主要的思路是把数据放到rear位置,然后rear后移一个位置。

不过要考虑数组是否为满,这是可以写一个isFull方法。

判断的条件是:rear 的下一个位置 是否是 front

java">    public boolean isFull() {return (rear+1) % elem.length == front;}

enQueue方法完整为下:

java">    //入队列public boolean enQueue(int value) {if(isFull()){return false;}elem[rear] = value;rear = (rear+1) % elem.length;return true;}

注意:rear后移一个位置不是rear++,而是(rear+1) % elem.length

出队列

deQueue方法

出队列的主要思路是:把front后移一个位置,前面的数据会被后面逐渐放进去的rear覆盖。

此时还要考虑数组是否为空,写一个isEmpty方法。判断条件是:front和rear是否相等。

java">    public boolean isEmpty() {return front == rear;}

出队列的完整代码为:

java">    //出队列public boolean deQueue() {if(isEmpty()){return false;}front = (front+1) % elem.length;return true;}
返回头队列

Front方法

  • 判断是否为空
  • 返回front位置的数据
java">    //返回头队列public int Front() {if(isEmpty()){return -1;}return elem[front];}
返回尾队列

Rear方法

  • 判断是否为空
  • 判断rear 是否为 0

之所以要判断rear == 0,是因为当rear == 0时,返回的是elem.length - 1,而rear != 0时,返回rear - 1;

完整代码为:

java">    public int Rear() {if(isEmpty()){return -1;}int index = (rear == 0) ? elem.length - 1 : rear-1;return elem[index];}

完整代码

双链表实现队列

java">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 = null;public ListNode last = null;public int useSize = 0;public void offer(int val){ListNode node = new ListNode(val);if(isEmpty()){first = last = node;}else{last.next = node;node.prev = last;last = last.next;}useSize++;}public int poll(){if(isEmpty()){return -1;}int val = first.val;first = first.next;//一个节点,就没必要再置空前一个节点if(first != null){first.prev = null;}useSize--;return val;}public int peek(){if(isEmpty()){return -1;}return first.val;}public boolean isEmpty(){return useSize == 0;//return first == 0;}
}

数组实现队列(设计循环队列)

java">class MyCircularQueue {public int front;public int rear;public int[] elem;public MyCircularQueue(int k) {this.elem = new int[k+1];}//入队列public boolean enQueue(int value) {if(isFull()){return false;}elem[rear] = value;rear = (rear+1) % elem.length;return true;}//出队列public boolean deQueue() {if(isEmpty()){return false;}front = (front+1) % elem.length;return true;}//返回头队列public int Front() {if(isEmpty()){return -1;}return elem[front];}//返回尾队列public int Rear() {if(isEmpty()){return -1;}int index = (rear == 0) ? elem.length - 1 : rear-1;return elem[index];}public boolean isEmpty() {return front == rear;}public boolean isFull() {return (rear+1) % elem.length == front;}
}


http://www.ppmy.cn/devtools/105325.html

相关文章

【机器学习-神经网络】循环神经网络

【作者主页】Francek Chen 【专栏介绍】 ⌈ ⌈ ⌈Python机器学习 ⌋ ⌋ ⌋ 机器学习是一门人工智能的分支学科,通过算法和模型让计算机从数据中学习,进行模型训练和优化,做出预测、分类和决策支持。Python成为机器学习的首选语言,…

OpenGL/GLUT实践:实现反弹运动的三角形动画与键盘控制(电子科技大学信软图形与动画Ⅱ实验)

源码见GitHub:A-UESTCer-s-Code 文章目录 1 运行效果2 实验过程2.1 环境配置2.2 绘制三角形2.2.1 渲染函数2.2.2 主函数2.2.3 运行结果 2.3 调整窗口大小2.4 简单动画与按键控制2.4.1 简单旋转2.4.2 键盘控制 2.5 窗口反弹动画2.5.1 处理窗口大小变化2.5.2 渲染函数…

安科瑞三相电能计量表ADL400/C 双向计量 CE认证 精度0.5S级

产品概述: 安科瑞ADL400是一款专为供电系统、工矿企业和公用事业设计的智能电表,具备小巧体积和方便安装的特点。‌ 它集成了常见的电力参数测量、电能计量及考核管理功能,能够提供前48个月的各类电能数据统计,并具备2~31次分次谐…

R18 XR :NR L2 enhancement

这篇主要看下为支持XR,L2都有哪些增强。主要分3个部分:(1)additionalBS-TableAllowed和Delay Status Report(DSR) (2)UE assistance info for UL traffic information (3) PDU set discard。正文开始: 为了增强 XR 上行资源的调度,引入了以下改进: (1)一个额外的buffer s…

9月2日复盘日记

9月2日复盘日记 前言今日感恩今日知识今日反思今日名言 前言 昨晚一直半睡半醒,早上就到七点半才醒,醒了之后做了45分钟活力瑜伽,严重暴汗。今天找到一位宝藏的瑜伽老师,虽然需要充电才能进行跟练,但感觉特别值当&…

牧野机床采集数据

牧野于1958年研发出日本第一数控铣床,并于1966年研发成功日本第一台加工中心。我在市面上常见的到的加工中心P5、P6系统,其余的就是EDM数控系统。他们两个用的不是同一种系统,采集方式也有区别,大家要注意。 牧野机床(中国)有限公司,于2002年7月23日在江苏昆山成立,是一…

【数据结构】—— 栈与队列

目录 前言一、栈1.1 堆栈原理1.2 栈的实现 二、队列2.1 队列的概念2.2 队列结构2.2.1 顺序队列2.2.2 链队 2.3 队列的实现 三、堆与栈的区别3.1 内存中的堆与栈3.2 数据结构中的堆与栈 结语 前言 在单片机数据处理的时候,如果在中断里添加太多函数,可能会…

ThinkPHP伪静态删除去掉内页url地址index.php

在使用Thinkphp后发现使用官方的伪静态规则后,手工/index.php/wxapp/11.html,这样也是能正常打开的,为了消除index.php把链接统一,可以把/index.php/wxapp/11.html301重定向到/wxapp/11.html 规则如下: #比如&#xf…