4.讲究先来后到的队列

news2025/7/22 9:32:19

概述

目标:

  1. 队列的存储结构及操作特点
  2. java中队列相关的api
  3. 基于单链表的队列实现
  4. 刷题(设计循环队列)

存储结构及特点

队列(queue) 和栈一样,代表具有一类操作特征的数据结构,拿日常生活中的一个场景举例说明,去车站的窗口买票,就要排队,先来的人就先买,后到的人就后买,先来的人排至队头,后来的人排至队尾,不允许插队,先进先出,这就是典型的队列;先进先出(First In First Out) 即 FIFO,为了方便理解队列这种数据结构,将以两幅图,第一个是队列,第二个是栈,两图作对比
在这里插入图片描述
在这里插入图片描述
总结: 队列和栈一样都属于一种操作受限的线性表,栈只允许在一端进行操作,分别是入栈和出栈,而队列跟栈很相似,支持的操作也有限,最基本的两个操作,一个叫入队对,将数据插入到队列末尾,另一个叫出队列,从队列头部取出一个数据
注意: 入队列和出队列的时间复杂度均为O(1)

队列实现

java api

队列这种数据结构在高级语言中的实现特别的丰富,成熟
Interface Queue 链接
全类名 java.util.Queue

									方法摘要
Throws exceptionReturns special value
Insertadd(e)offer(e)
Removeremove()poll()
Examineelement()peek()

链表实现队列

基于单链表实现的队列,需要两个指针:head指针和 tail 指针;它们分别指向链表的第一个 节点 ,如图所示,入队时, tail.next = new_nodetail = tail.next 即先添加到链表尾,再将 tail 指向新加的 节点,出队时, head = head.next 即将原来的第一个头节点,变为原来的第二个节点
在这里插入图片描述
实现时,将 java.util.Queue 直接复制过来
队列接口如下:

public interface Queue<E> {
    boolean add(E e);

    boolean offer(E e);

    E remove();

    E poll();

    E element();

    E peek();

    boolean isEmpty();
}

队列实现类如下:

public class LinkedListQueue<E> implements Queue<E> {
    // 队列大小
    int size;
    // 头节点
    Node<E> head;
    // 尾节点
    Node<E> tail;

    public LinkedListQueue() {
    }

    @Override
    public boolean add(E e) {
        addTail(e);
        return true;
    }

    @Override
    public boolean offer(E e) {
        addTail(e);
        return true;
    }

    @Override
    public E remove() {
        if (size == 0) {
            throw new NoSuchElementException("队列为空!");
        }
        return removeHead().val;
    }

    @Override
    public E poll() {
        if (size == 0) {
            return null;
        }
        return removeHead().val;
    }

    @Override
    public E element() {
        if (size == 0) {
            throw new NoSuchElementException("队列为空!");
        }
        return head.val;
    }

    @Override
    public E peek() {
        if (size == 0) {
            return null;
        }
        return head.val;
    }

    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder();
        Node<E> h = head;
        while (h != null) {
            sb.append(h.val).append("->");
            h = h.next;
        }
        return sb.append("null").toString();
    }

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

    private Node<E> removeHead() {
        Node<E> h = head;
        head = head.next;
        h.next = null;
        size--;
        return h;
    }

    private void addTail(E item) {
        Node<E> tmp = tail;
        Node<E> newNode = new Node<>(item, null);
        tail = newNode;
        if (tmp == null) {
            // 链表为空,即入队既是头又是尾
            head = newNode;
        } else {
            // tmp 此是是倒数第二个节点
            tmp.next = tail;
        }
        size++;
    }

    private static class Node<E> {
        E val;
        Node<E> next;

        public Node(E val, Node<E> next) {
            this.val = val;
            this.next = next;
        }
    }
}

测试类如下:

public static void main(String[] args) {
        Queue<String> queue = new LinkedListQueue();
        queue.add("1");
        queue.add("2");
        queue.add("3");
        System.out.println("队列是否为空:" + queue.isEmpty());
        System.out.println(queue);
        System.out.println("出队元素:"+queue.remove());
        System.out.println(queue);
        System.out.println("出队元素:"+queue.poll());
        System.out.println(queue);
        System.out.println("队列头元素:"+queue.peek());
        System.out.println(queue);
    }

刷题(设计循环队列)

设计循环队列
为充分利用队列空间,克服"假溢出"现象的方法是:将队列空间想象为一个首尾相接的圆环,循环队列(Circular Queue)是把顺序队列首尾相连,把存储队列元素的表从逻辑上看成一个环,成为循环队列
在这里插入图片描述

在循环队列中,当队列为空时,可知 front = rear;而当所有队列空间全占满时,也有 front = rear 。为了 区别 这两种情况,假设队列使用的数组有 capacity 个存储空间,则此时规定循环队列最多只能有 capacity - 1 个队列元素,当循环队列中只剩下一个空间存储单元时,则表示队列已满;根据以上可知,队列判空条件是 front = rear ,而队列判断为满的条件是 front = (rear + 1) mod capacity ,如上图队列已满。对于固定大小的数组,只要知道队尾 rear 与队首 front ,即可计算出队列当前的长度:(rear - front + capacity) mod capacity,如下图
在这里插入图片描述

此时由公式:0 - 1 + 5 % 5 = 4 队列长度为 4

分析完来看代码

public class MyCircularQueue {

    private int[] data;
    private int front, rear;

    public MyCircularQueue(int k) {
        // 因为满队列实际上是数组少1个,所以加上1
        data = new int[k + 1];
    }

    public boolean enQueue(int value) {
        if (isFull()) {
            return false;
        }
        data[rear] = value;
        // 不能直接 rear ++ ,值会无限增大
        rear = getNext(rear);
        return true;
    }

    public boolean deQueue() {
        if (isEmpty()) {
            return false;
        }
        front = getNext(front);
        return true;
    }

    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder();
        sb.append("头节点下标:" + front).append(",").append("尾节点下标:" + rear).append(" ");
        for (int i = 0; i < this.data.length; i++) {
            sb.append("a[").append(i).append("] = ").append(this.data[i]).append(",");
        }
        return sb.toString();
    }

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

    public boolean isFull() {
        return getNext(rear) == front;
    }

    private int getNext(int cur) {
        // 获取当前数据的下一个数据的下标
        return (cur + 1) % data.length;
    }
}

测试如下图,队列满,然后出一个进一个,重复两次执行
在这里插入图片描述
测试

public class MyCircularQueueTest {
    public static void main(String[] args) {
        MyCircularQueue queue = new MyCircularQueue(5);
        System.out.println("队列是否为空:" + queue.isEmpty());
        queue.enQueue(1);
        System.out.println(queue);
        queue.enQueue(2);
        queue.enQueue(3);
        queue.enQueue(4);
        queue.enQueue(5);
        System.out.println(queue);
        System.out.println("加入是否成功!" + queue.enQueue(5));
        queue.deQueue();
        System.out.println("队列头部元素出队:" + queue);
        System.out.println("加入是否成功!" + queue.enQueue(6));
        System.out.println(queue);
        // -----
        queue.deQueue();
        System.out.println("队列头部元素出队:" + queue);
        System.out.println("加入是否成功!" + queue.enQueue(7));
        System.out.println(queue);

    }
}

结束

队列 至此就结束了,如有问题,欢迎评论区留言

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

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

相关文章

百度上传自己个人简介攻略,个人介绍百度百科怎么做?

个人介绍要展示在百度百科上该怎么操作&#xff0c;我们都清楚百度百科词条是需要申请才能拥有的&#xff0c;但是没有百度上传自己个人简介的攻略&#xff0c;很多人是不知从何下手的。下面洛希爱做百科网带着大家一起来了解。 一、了解百度百科词条的创建规则 1. 词条名称规…

python项目部署代码汇总:目标检测类、人体姿态类

一、AI健身计数 1、图片视频检测 &#xff08;cpu运行&#xff09;&#xff1a; 注&#xff1a;左上角为fps&#xff0c;左下角为次数统计。 1.哑铃弯举&#xff1a;12&#xff0c;14&#xff0c;16 详细环境安装教程&#xff1a;pyqt5AI健身CPU实时检测mediapipe 可视化界面…

光学雨量计:更灵敏可靠、更智能的降雨监测工具

光学雨量计&#xff1a;更灵敏可靠、更智能的降雨监测工具 降雨量信息是评估大气环境和降水研究的关键指标&#xff0c;也是环境监测和农业安全监测的重要参数。目前&#xff0c;我们通常使用翻斗式或光学雨量计来监测降雨量&#xff0c;这些工具能够感知自然界的降雨量&#…

媒体宣传如何助力品牌发展

传媒如春雨&#xff0c;润物细无声&#xff0c;大家好&#xff0c;我是51媒体网胡老师。 媒体宣传可以在多方面助力品牌发展&#xff0c;下面是一些关键的方式&#xff1a; 1. 提高品牌知名度&#xff1a;媒体宣传可以将品牌曝光给更广泛的受众&#xff0c;使更多人了解您的品…

内涝积水监测仪怎么样?万宾科技城市内涝积水监测的作用

在城市建设发展过程中&#xff0c;道路基础设施的建设永远都占据着重要一席&#xff0c;因为人们出行一旦受阻便会影响城市进展&#xff0c;也会影响经济发展。在城市之中有隧道&#xff0c;下穿式立交桥等容易存积水的地方&#xff0c;一旦出现恶劣暴雨天气&#xff0c;这些地…

CHAT——新手必看的文章

今天小编用CHAT写一篇文章&#xff1a;Ipad新手注意事项&#xff0c;一定要看。 标题&#xff1a;iPad新手必读&#xff1a;一篇你绝对不能错过的关于iPad使用的注意事项 当你买了一台全新的iPad&#xff0c;无论是为了工作还是娱乐&#xff0c;这款强大而引人入胜的设备都提供…

Wonder3D:用单张图片生成纹理网格

Wonder3D 只需 2 ∼ 3 分钟即可从单视图图像重建高度详细的纹理网格。 Wonder3D首先通过跨域扩散模型生成一致的多视图法线图和相应的彩色图像&#xff0c;然后利用新颖的法线融合方法实现快速、高质量的重建。 推荐&#xff1a;用 NSDT编辑器 快速搭建可编程3D场景 1、推理准…

Linux ---------------------Shell 基本运算符

&#xff08;一&#xff09;摘要 Shell 和其他编程语言一样&#xff0c;支持多种运算符&#xff0c;包括&#xff1a; 算数运算符关系运算符布尔运算符字符串运算符文件测试运算符 原生bash不支持简单的数学运算&#xff0c;但是可以通过其他命令来实现&#xff0c;例如 awk …

界面控件DevExpress WinForms Gauge组件 - 实现更高级别数据可视化

DevExpress WinForms控件包含了超过150个随时可用的仪表盘预设&#xff0c;包括圆形&#xff0c;数字&#xff0c;线性和状态指示器等&#xff0c;来帮助用户实现更高级的数据可视化。 DevExpress WinForms有180组件和UI库&#xff0c;能为Windows Forms平台创建具有影响力的业…

解决ubunut20.04系统麦克风异常问题

背景 在部分ubunut环境中&#xff0c;我们指定了麦克风的下标&#xff0c;使用指定的麦克风有问题&#xff0c;只能录音一次&#xff0c;第二次就失效了&#xff0c;不过只是部分ubunut系统会遇到这个情况 # 找到以usb_mic_prefix为前缀的麦克风下标 import speech_recognitio…

(五)上市企业实施IPD成功案例分享之——迈瑞医疗

医疗器械企业是被严格监管的行业&#xff0c;同时也是市场充分竞争的行业。医疗器械细分市场众多&#xff0c;需求强劲&#xff0c;存在着巨大的商机&#xff0c;被称为永远的朝阳行业。但是&#xff0c;存在商机并不等于能够抓住商机。不同的医疗器械企业在同样的宏观环境、细…

Matplotlib教程(非常详细)(第一部分)

Matplotlib是一款免费开源的Python数据可视化工具。 Matplotlib 是 Python 中最受欢迎的数据可视化软件包之一&#xff0c;支持跨平台运行&#xff0c;它是 Python 常用的 2D 绘图库&#xff0c;同时它也提供了一部分 3D 绘图接口。Matplotlib 通常与 NumPy、Pandas 一起使用&…

序列图(顺序图)

1.序列图(顺序图)概念 序列图(顺序图)是用来显示参与者如何以一系列顺序的步骤与系统的对象交互的模型。 顺序图可以用来展示对象之间是如何进行交互的。 顺序图将显示的重点放在消息序列上&#xff0c;即强调消息是如何在对象之间被发送和接收的&#xff0c;其中循环、选择…

2021年06月 Python(三级)真题解析#中国电子学会#全国青少年软件编程等级考试

Python等级考试&#xff08;1~6级&#xff09;全部真题・点这里 一、单选题&#xff08;共25题&#xff0c;每题2分&#xff0c;共50分&#xff09; 第1题 关于open()函数的参数&#xff0c;下列描述正确的是&#xff1f; A: “w” 以十六进制格式打开一个文件只用于写入 B:…

录屏工具大揭秘!让你轻松成为录像达人

在日常生活中&#xff0c;我们经常需要使用录屏工具来记录电脑屏幕上的操作过程&#xff0c;比如制作教程视频、分享游戏经验、展示软件功能等&#xff0c;一个优秀的录屏工具能帮上大忙。现在市面上有许多录屏工具可供选择&#xff0c;本文将详细介绍三种工具的使用方法和优势…

C语言--输出格式控制(printf函数)--宽度精度控制

格式输出函数printf printf(格式控制&#xff0c;输出表列) 基本用法 格式字符功能例子d输出一个有符号的十进制整数printf("%d %d",12,-56);c输出一个字符 char ch a; printf("%c",ch); s输出一个字符串printf("%s","oh my god&…

成为MySQL大师的第一步:轻松学习MySQL数据库的终极指南!

数据库开发-MySQL 1. MySQL概述1.1 安装1.1.1 版本1.1.2 安装1.1.3 连接1.1.4 企业使用方式 1.2 数据模型1.3 SQL简介1.3.1 SQL通用语法1.3.2 分类 2. 数据库设计-DDL2.2 数据库操作2.2.1 查询数据库2.2.2 创建数据库2.2.3 使用数据库2.2.4 删除数据库 2.3 图形化工具2.3.1 介绍…

vue2 运行报错Parsing error: The keyword ‘import‘ is reserved

在配置文件.eslintrc.js中配置parserOptions来指定语言版本和模块类型 {"parserOptions": {"ecmaVersion": 7,"sourceType": "module"} }

物联网AI MicroPython传感器学习 之 SHT3X温湿度传感器

学物联网&#xff0c;来万物简单IoT物联网&#xff01;&#xff01; 一、产品简介 Sensirion SHT3x-DIS湿度和温度传感器基于CMOSens传感器芯片&#xff0c;更加智能、可靠&#xff0c;精度更高。SHT3x-DIS具有增强的信号处理能力、两个独特的用户可选I2C地址&#xff0c;通信…

Vectrosity 插件使用

1 下载 2 使用&#xff0c;目前在2020.3.3上测试可以 导入时选5.6 再导入demo