数据结构Java版(3)——队列Queue

news2024/9/29 0:12:22

一、概念

        队列也是一种线性数据结构,最主要的特点是入队列顺序和出队列顺序是相同的,操作时在队尾入队,在队首出队。在Java中给我们提供了一个泛型队列——Queue,其中最常用的方法有:

  1. void offer():入队
  2. E poll():出队
  3. E peek():查看队首元素
  4. int size():返回队中元素
  5. boolean isEmpty():检查队列是否为空

二、队列的实现

       因为队列也是一种线性结构,所以这里可以利用之前我们写的数组,这里可以用接口的方式来实现我们自己的顺序队列,下面进行代码演示。

队列的接口

public interface Queue_i<Elem> {
    public abstract boolean offer(Elem e);
    public abstract Elem poll();
    public abstract Elem peek();
    public abstract int getLength();
    public abstract boolean isEmpty();
    public abstract Elem peekLast();
}

通过接口的方式,对queue中的方法进行重写,实现功能 

public class ArrQueue<E> implements Queue_i<E>{
    private MyArray<E> queue;
    private int length;

    public ArrQueue() {
        this.queue = new MyArray<>(16);
        length = 0;
    }

    @Override
    public boolean offer(E e) {
        try{
            this.queue.add(e);
        }catch (Exception exception){
            return false;
        }
        length++;
        return true;
    }

    @Override
    public E poll() {
        if (isEmpty()) return null;
        E e;
        try{
            e = this.queue.removeByIndex(0);
        }catch (Exception exception){
            return null;
        }
        this.length--;
        return e;
    }

    @Override
    public E peek() {
        if (isEmpty()) return null;
        E e;
        try{
            e = this.queue.getValueByIndex(0);
        }catch (Exception exception){
            return null;
        }
        return e;
    }

    @Override
    public int getLength() {
        return this.length;
    }

    @Override
    public boolean isEmpty() {
        return getLength()==0;
    }

    @Override
    public E peekLast() {
        if (isEmpty()) return null;
        E e;
        try{
            e = this.queue.getValueByIndex(this.length-1);
        }catch (Exception exception){
            return null;
        }
        return e;
    }
}

 对自己的顺序队列进行代码测试 

import java.util.ArrayList;
import java.util.List;
import java.util.Random;

public class testMyQueue {
    public static void test(Queue_i<Integer> queue, List<Integer> list){
        Random random = new Random();
        for(int i = 0;i < 10;i++){
            queue.offer(random.nextInt(1000));
            System.out.println(queue.peekLast()+"——现在还有"+queue.getLength()+"个元素");
        }
        Integer temp;
        while ((temp = queue.poll())!=null){
            list.add(temp);
        }
        System.out.println();
    }

    public static void main(String[] args) {
        List<Integer> list = new ArrayList();
        Queue_i<Integer> queue = new ArrQueue<>();
        test(queue,list);
        for (Integer i:list) {
            System.out.println(i);
        }
    }
}

输出结果:

        通过观察可知,队列具有先进先出的特点。

三、循环队列

         因为顺序队列每次出队时都要把所有元素向前移动一位,时间复杂度高,但如果用双指针,则会导致假溢出现象出现,为了解决这个问题,我们提出了循环队列这个概念。

通过接口的方式,对queue中的方法进行重写,实现功能 

public class LoopQueue<T> implements Queue_i<T>{
    private MyArray<T> queue;
    private int front;
    private int rear;

    public LoopQueue() {
        this.queue = new MyArray<>(17);
        this.front = 0;
        this.rear = 0;
    }

    @Override
    public boolean offer(T t) {
        try{
            queue.add(rear, t);
        }catch (Exception e){
            return false;
        }
        rear =  (rear + 1)%queue.getSize();
        return true;
    }


    @Override
    public T poll() {
        if(isEmpty()) return null;
        T t;
        try{
            t = queue.removeByIndex(front);
        }catch (Exception e){
            return null;
        }
        front = (front+1)%queue.getSize();
        return t;
    }

    @Override
    public T peek() {
        if(isEmpty()) return null;
        T t;
        try{
            t = queue.getValueByIndex(front);
        }catch (Exception e){
            return null;
        }
        return t;
    }

    @Override
    public int getLength() {
        return (rear + queue.getSize() - front)%queue.getSize();
    }

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

    @Override
    public T peekLast() {
        if(isEmpty()) return null;
        T t;
        try{
            t = queue.getValueByIndex((rear - 1 + queue.getSize())%queue.getSize());
        }catch (Exception e){
            return null;
        }
        return t;
    }
}

        这里需要注意的时,因为循环队列两个指针能循环使用的原因,我们判断队列是否为空和为满时会出现冲突,即两个条件都是rear==front,为了解决这个问题,我们牺牲了一个空间,以区别为空和为满,则为空条件不变,为满条件变为(rear+1)%总容量==front,这个就导致我们在数组扩容时出现问题,这里有两个解决方案,一是将数组中的方法进行重新,二是将数组的长度初始值设为一,以填补浪费掉的空间。这里还有一个注意点是要重新数组中的删除方法,仅删除不调动位置。

对循环队列的测试

import java.util.ArrayList;
import java.util.List;
import java.util.Random;

public class testMyQueue {
    public static void test(Queue_i<Integer> queue, List<Integer> list){
        Random random = new Random();
        for(int i = 0;i < 10;i++){
            queue.offer(random.nextInt(1000));
            System.out.println(queue.peekLast()+"——现在还有"+queue.getLength()+"个元素");
        }
        Integer temp;
        while ((temp = queue.poll())!=null){
            list.add(temp);
        }
        System.out.println();
    }

    public static void test(Queue_i<Integer> queue){
        List<Integer> list = new ArrayList();
        Random random = new Random();
        for(int i = 0;i < 20;i++){
            queue.offer(random.nextInt(1000));
            System.out.println(queue.peekLast()+"——现在还有"+queue.getLength()+"个元素");
        }
        Integer temp;
        while ((temp = queue.poll())!=null){
            list.add(temp);
        }
        for (Integer i:list) {
            System.out.println(i);
        }

    }

    public static void main(String[] args) {
        List<Integer> list = new ArrayList();
        Queue_i<Integer> queue = new ArrQueue<>();
        Queue_i<Integer> queue2 = new LoopQueue<>();
        test(queue2);
//        test(queue,list);
//        for (Integer i:list) {
//            System.out.println(i);
//        }
    }
}

输出结果:

四、队列可以解决的问题

1.进行异步操作,在多线程编程时减少线程阻塞现象

        这里具体操作可以去看之前一篇浏览器事件循环的文字,其中对浏览器的异步操作进行了详细讲解,其中就用到了队列的知识:

浏览器事件循环-CSDN博客

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

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

相关文章

Ubuntu下将nvidia-smi封装为GUI界面,实时查看显卡信息

和win系统不同的是&#xff0c;在Ubuntu端&#xff0c;系统级的系统监视器中&#xff0c;只能查看内存、CPU和网络状态&#xff0c;并不能查看GPU状态 而使用NVIDIA显卡的朋友都知道一条指令 nvidia-smi 在终端运行后即可查看显卡信息、资源占用情况等 但是这样会占用终端&am…

轮胎侧偏刚度线性插值方法

一、trucksim取数据 步骤一 步骤二 二、数据导入到matlab中 利用simulink的look up table模块 1是侧偏角&#xff1b;2是垂直载荷&#xff1b;输出是侧向力。 侧向力除以侧偏角就是实时的侧偏刚度。

排序:计数排序

目录 思想&#xff1a; 操作步骤&#xff1a; 思路&#xff1a; 注意事项&#xff1a; 优缺点&#xff1a; 代码解析&#xff1a; 完整代码展示&#xff1a; 思想&#xff1a; 计数排序又称为鸽巢原理&#xff0c;是对哈希直接定址法的变形应用。 操作步骤&#xff…

Baumer工业相机堡盟工业相机如何通过NEOAPI SDK使用Binning像素合并功能(C#)

Baumer工业相机堡盟工业相机如何通过NEOAPI SDK使用Binning像素合并功能&#xff08;C#&#xff09; Baumer工业相机Baumer工业相机NEOAPI SDK和短曝光功能的技术背景Baumer工业相机通过CameraExplorer软件使用Binning功能Baumer工业相机通过NEOAPI SDK使用Binning功能1.引用合…

2018年认证杯SPSSPRO杯数学建模C题(第二阶段)机械零件加工过程中的位置识别全过程文档及程序

2018年认证杯SPSSPRO杯数学建模 基于轮廓提取与图像配准的零件定位问题研究 C题 机械零件加工过程中的位置识别 原题再现&#xff1a; 在工业制造自动生产线中&#xff0c;在装夹、包装等工序中需要根据图像处理利用计算机自动智能识别零件位置&#xff0c;并由机械手将零件…

python数字图像处理基础(九)——特征匹配

目录 蛮力匹配&#xff08;ORB匹配&#xff09;RANSAC算法全景图像拼接 蛮力匹配&#xff08;ORB匹配&#xff09; Brute-Force匹配非常简单&#xff0c;首先在第一幅图像中选取一个关键点然后依次与第二幅图像的每个关键点进行&#xff08;描述符&#xff09;距离测试&#x…

爆推联盟,推广接单平台定制开发(智创有术)

爆推联盟官网、推广接单平台、很多朋友问我做项目要怎么做&#xff0c;项目怎么选&#xff1f;那些项目比较稳定靠谱&#xff0c;赚钱还不错的平台&#xff0c;其实网上的项目很多&#xff0c;别说做&#xff0c;看都看不过来&#xff0c;我们做项目最主要的就是稳定嘛&#xf…

智能化未来:NFC技术助力数字化社区

引言 数字化转型深刻改变着社区管理的方式&#xff0c;其中NFC技术作为一种近场通讯技术&#xff0c;正在为数字社区的智能化未来提供强有力的支持。 NFC技术简介 近场通讯技术(NFC)是一种无线通信技术&#xff0c;能够实现设备之间的近距离通讯。在数字社区建设中&#xf…

第一讲_HarmonyOS应用开发环境准备

HarmonyOS应用开发环境准备 1. 知识储备2. 环境搭建2.1 安装node.js2.2 配置node.js2.3 安装命令行工具2.4 安装DevEco Studio2.5 配置DevEco Studio 1. 知识储备 HarmonyOS提供了一套UI开发框架&#xff0c;即方舟开发框架&#xff08;ArkUI框架&#xff09;。方舟开发框架可…

#开发环境篇:HBuilderX自定义括号颜色激活时list和tab的背景色

Settings.json 配置 位置在 设置------> 源码设置里面 {"beautify.useProjectConfigFile": true,"browsers.config": {"Chrome.path": "C:/Program Files/Google/Chrome/Application/chrome.exe"},"defaultFomat.vue":…

判断SD-WAN是否适用于你的企业的关键问题

企业网络的演进已经将SD-WAN&#xff08;软件定义广域网&#xff09;推到了风口浪尖。不论企业规模如何&#xff0c;它们都在寻求适应不断变化的网络环境的最佳解决方案。尽管SD-WAN的部署带来了多方面的优势&#xff0c;但企业在决定是否采用SD-WAN时需要考虑一些关键问题。 关…

SafeTpack—基于AURIX 2G的功能安全目标解决方案

产品概述 SafeTpack是专门针对于英飞凌AURIX 2G系列芯片的功能安全解决方案&#xff0c;由英飞凌下属子公司Hitex按照ISO26262-10作为独立于环境的安全要素&#xff08;SEOOC&#xff09;研发。根据ISO26262-5中的要求&#xff0c;系统需要根据不同ASIL等级的要求&#xff0c;针…

目标文献分析方法

如何正确选题&#xff1f; 不仅仅是题目&#xff0c;而是研究工作的起步选题步骤&#xff1f; 发现问题选择方向调查研究分析论证确定选题 中国知网 深度学习方向词 1检索&#xff1a;深度学习 医疗影像 1 发表时间要最新 2 显示50个&#xff0c;全选 3 导出文献格式Ref 4 导…

JVM垃圾回收机制及思维导图

一、Java垃圾回收机制 在java中&#xff0c;程序员是不需要显示的去释放一个对象的内存的&#xff0c;而是由虚拟机自行执行。在JVM中&#xff0c;有一个垃圾回收线程&#xff0c;它是低优先级的&#xff0c;在正常情况下是不会执行的&#xff0c;只有在虚拟机空闲或者当前堆内…

官宣!Meta正在训练Llama 3,将继续开源

1月19日&#xff0c;全球社交、科技巨头Meta的联合创始人兼首席执行官-Zuck&#xff08;扎克伯格&#xff09;在is宣布&#xff0c;正在训练Llama 3并且以负责任地方式继续开源。 Zuck表示&#xff0c;预计到2024年底&#xff0c;Meta将拥有350,000块H100&#xff0c;如果算上…

JAVA SECS发送Report C#处理SECS Report SECS发送事件资料大全 S6F11 建立通讯S1F13

发送S6F11非常简单&#xff0c;只需5~6行代码&#xff0c;最核心是代码清晰易懂。 任何人都可以一看就能上手&#xff0c;如果说用代码可读性作为不可替代性的壁垒就无话可说了。 private void buttonS6F11_Click(object sender, EventArgs e) {int nTransaction 0;// 数据部…

Java中创建List接口、ArrayList类和LinkedList类的常用方法(一)

List接口 要了解List接口&#xff0c;就不得不说起Java的集合框架。 &#xff08;该图来自菜鸟教程&#xff09; Collection接口和Map接口 Java 集合框架主要包括两种类型的容器&#xff0c;集合Collection和图Map。 Collection接口代表了单列集合&#xff0c;它包含了一组…

画面滤镜特效SDK,企业级视频处理技术方案

视频处理技术日新月异&#xff0c;对于企业而言&#xff0c;如何快速、高效地处理视频内容&#xff0c;增加其观赏性和吸引力&#xff0c;成为了一项重要的挑战。美摄科技画面滤镜特效SDK&#xff0c;作为一款全面的视频处理工具&#xff0c;为企业提供了一种高效、灵活的视频处…

元宇宙:智慧城市建设的未来引擎与价值之源

在21世纪的技术大潮中&#xff0c;元宇宙的出现无疑是一场革命&#xff0c;其独特的概念与价值已经引发了全球范围内的关注。 作为新兴科技的前沿&#xff0c;元宇宙为智慧城市建设带来了无限的可能性和价值&#xff0c;有望成为未来城市发展的核心动力。 元宇宙&#xff0c;这…

虚拟线程探索与实践(JDK19)

优质博文&#xff1a;IT-BLOG-CN 一、简介 虚拟线程是轻量级线程&#xff0c;极大地减少了编写、维护和观察高吞吐量并发应用的工作量。虚拟线程是由JEP 425提出的预览功能&#xff0c;并在JDK 19中发布&#xff0c;JDK 21中最终确定虚拟线程&#xff0c;以下是根据开发者反馈…