Java手写数组队列和链表队列并使用java里面现成的队列方法

news2024/11/25 23:27:01

Java队列实现与常用使用方法介绍

  • 说明
  • 使用数组手动实现队列功能
  • 使用单向链表手动实现队列功能
  • Java中ArrayBlockingQueue和ArrayQueue和LinkedBlockingQueue使用
    • ArrayQueue使用方法如下:
    • ArrayBlockingQueue常用使用方法如下:
    • LinkedBlockingQueue常用使用方法如下:
    • ArrayBlockingQueue和LinkedBlockingQueue区别

说明

这里记录下使用数组和链表手动实现队列功能,并使用java里面现成的队列方法。

使用数组手动实现队列功能

package com.example.deesign_patterns.test;

//java使用数组简单实现队列
public class ArrayQueue {
    private int[] queue;  // 内部数组
    private int front;    // 队列头部指针
    private int rear;     // 队列尾部指针
    private int size;     // 队列当前元素个数
    private int capacity; // 队列容量

    //构造方法,初始化的时候必须要传队列容量值
    public ArrayQueue(int capacity) {
        this.capacity = capacity;
        queue = new int[capacity];
        front = 0;
        rear = -1;
        size = 0;
    }

    //判断是否是空队列
    public boolean isEmpty() {
        return size == 0;
    }

    //判断队列是否已满
    public boolean isFull() {
        return size == capacity;
    }

    //队列元素个数
    public int size() {
        return size;
    }

    //元素入队列
    public void add(int value) {
        if (isFull()) {
            System.out.println("队列已经满了,无法添加队列。");
            return;
        }
        rear = (rear + 1) % capacity; // 循环队列,计算新的尾部位置
        queue[rear] = value;//在数组尾部添加元素
        size++;//如果添加成功,则队列元素数量加1
        System.out.println("入队列元素值: " + value);
    }

    //头部元素出队列,重新计算头部位置,数组索引往后移了一位,相当于删除头元素
    public int pull() {
        if (isEmpty()) {
            System.out.println("队列是空的,无法出队列。");
            return -1;
        }
        int value = queue[front];
        front = (front + 1) % capacity; // 循环队列,计算新的头部位置
        size--;//如果出队列成功,则队列元素数量减1
        System.out.println("出队列元素值: " + value);
        return value;
    }

    //获取队列里面的首元素,不会删除元素
    public int peek() {
        if (isEmpty()) {
            System.out.println("队列是空的!");
            return -1;
        }
        return queue[front];
    }

    //显示队列元素
    public void display() {
        if (isEmpty()) {
            System.out.println("队列是空的!");
            return;
        }
        System.out.print("队列当前元素值: ");
        int index = front;
        for (int i = 0; i < size; i++) {
            System.out.print(queue[index] + " ");
            index = (index + 1) % capacity; // 循环遍历队列
        }
        System.out.println();
    }

    //测试类
    public static void main(String[] args) {
        ArrayQueue queue = new ArrayQueue(5);
        queue.add(10);
        queue.add(20);
        queue.add(30);
        queue.display(); // Queue: 10 20 30
        queue.pull();
        queue.display(); // Queue: 20 30
        queue.add(40);
        queue.add(50);
        queue.display(); // Queue: 20 30 40 50
        queue.pull();
        queue.pull();
        queue.display(); // Queue: 40 50
        System.out.println("当前队列首元素为:"+queue.peek());//Queue: 40
    }
}


执行结果如下:
在这里插入图片描述

使用单向链表手动实现队列功能

单向链表类

package com.example.deesign_patterns.test;

//单向链表类
public class Node<T> {
    public T data;
    public Node next;

    //无参构造方法
    public Node() {}

    //有参构造方法
    public Node(T data, Node next) {
        this.data = data;
        this.next = next;
    }

    public T getData() {
        return data;
    }

    public void setData(T data) {
        this.data = data;
    }

    public Node getNext() {
        return next;
    }

    public void setNext(Node next) {
        this.next = next;
    }
}

队列需要实现的功能接口(也可以在链表队列类里面直接写方法):

package com.example.deesign_patterns.test;

/**
 * 队列功能接口
 * 队列是一种先进先出的线性表
 * 只能在表的一端进行插入,另一段进行删除
 * 允许插入的一端叫队尾,允许删除的一端叫队头()
 */
public interface IQueue<T> {
    /**
     * 初始化队列 构造一个空队列
     */
    IQueue InitQueue();

    /**
     * 销毁队列
     */
    IQueue DestroyQueue();

    /**
     * 清空队列
     */
    IQueue ClearQueue();

    /**
     * 队列判空
     */
    Boolean isEmpty();

    /**
     * 返回队列长度
     */
    Integer QueueLength();

    /**
     * 返回队列头元素
     */
    T GetHead();

    /**
     * 插入队尾元素
     */
    Boolean EnQueue(T e);

    /**
     * 删除队头元素  即出队
     */
    T DeQueue();

    /**
     * 打印队列元素
     */
    void printQueue();
}

链表队列类:

package com.example.deesign_patterns.test;

//java使用链表简单实现队列
public class LinkedQueue<T> implements IQueue<T> {
    private  Node<T> front;//队头指针
    private  Node<T> rear;//队尾指针
    private int size;//队列长度

    //无参构造方法
    public LinkedQueue() {
        front = null;
        rear = null;
        size = 0;
    }

    //初始化队列方法
    @Override
    public IQueue InitQueue() {
        front = null;
        rear = null;
        size = 0;
        return this;
    }

    //销毁队列方法
    @Override
    public IQueue DestroyQueue() {
        //销毁
        front = null;
        rear = null;
        size = 0;
        return this;
    }

    //清空队列方法
    @Override
    public IQueue ClearQueue() {
        front = null;
        rear = null;
        size = 0;
        return this;
    }

    //判断队列是否为空
    @Override
    public Boolean isEmpty() {
        return size == 0;
    }

    //判断队列长度
    @Override
    public Integer QueueLength() {
        return size;
    }

    //获取队列里面的首元素
    @Override
    public T GetHead() {
        if (isEmpty()) {
            return null;
        }
        return front.getData();
    }

    //将元素入队
    @Override
    public Boolean EnQueue(T e) {
        Node<T> newNode = new Node<>(e, null);
        if (isEmpty()) {
            front = newNode;
        } else {
            rear.setNext(newNode);
        }
        rear = newNode;
        size++;
        return true;
    }

    //将元素出队
    @Override
    public T DeQueue() {
        if (isEmpty()) {
            return null;
        }
        T data = front.getData();
        front = front.getNext();
        size--;
        if (isEmpty()) {
            rear = null;
        }
        return data;
    }

    @Override
    public void printQueue() {
        for (Node current = front;current != null;current = current.next){
            System.out.print(current.data+" ");
        }
        System.out.println();
    }
	
	//测试类
    public static void main(String[] args) {
        IQueue<Integer> queue = new LinkedQueue<>();
        queue.InitQueue();
        queue.EnQueue(1);
        queue.EnQueue(2);
        queue.EnQueue(3);
        System.out.println("队列长度: " + queue.QueueLength());
        queue.printQueue();//打印队列值
        System.out.println("队头元素: " + queue.GetHead());
        System.out.println("出队元素: " + queue.DeQueue());
        System.out.println("出队元素: " + queue.DeQueue());
        System.out.println("出队元素: " + queue.DeQueue());
        queue.printQueue();//打印队列值
        System.out.println("队列长度: " + queue.QueueLength());
        System.out.println("队列是否为空: " + queue.isEmpty());
    }
}

在这里插入图片描述

Java中ArrayBlockingQueue和ArrayQueue和LinkedBlockingQueue使用

在Java中,ArrayBlockingQueue和ArrayQueue是两种不同的队列实现。它们之间有以下区别:

  1. 数据结构不同:ArrayBlockingQueue是基于数组的有界阻塞队列,它的容量是固定的。而ArrayQueue是基于数组的无界队列,它的容量可以动态增长。
  2. 插入和删除操作的不同:ArrayBlockingQueue的插入和删除操作是线程安全的,并且支持阻塞操作。当队列已满时,插入操作将会被阻塞,直到有空间可用;当队列为空时,删除操作将会被阻塞,直到有元素可用。而ArrayQueue的插入和删除操作不是线程安全的,需要自行处理同步。
  3. 性能方面的不同:由于ArrayBlockingQueue支持阻塞操作,它在多线程环境下具有更好的线程安全性。然而,由于需要处理同步和阻塞,它的性能相对较低。相比之下,ArrayQueue在单线程环境下的性能更好,不需要处理同步和阻塞。

ArrayQueue使用方法如下:

package com.example.deesign_patterns.test;

import com.sun.jmx.remote.internal.ArrayQueue;

public class Test3Main {

    public static void main(String[] args) {
        //数组队列使用,给数组一个大小,当数组里面的元素数量超过5,就会报错,可以通过resize()方法扩容
        ArrayQueue arrayQueue=new ArrayQueue<Integer>(5);
        arrayQueue.add(1);//入队列
        arrayQueue.add(2);
        arrayQueue.add(3);
        arrayQueue.add(4);
        arrayQueue.add(5);
        System.out.println("当前队列元素:"+arrayQueue);
        System.out.println("当前队列大小:"+arrayQueue.size());
        System.out.println("获取当前队列索引为1的元素:"+arrayQueue.get(1));
        //重新设置队列大小,相当于扩容,扩容后大小由原来的5变为6,值必须比原来大
        arrayQueue.resize(6);
        arrayQueue.add(6);
        System.out.println("当前队列元素:"+arrayQueue);
        System.out.println("当前队列大小:"+arrayQueue.size());
        //只能删除队列头元素,必须是索引0,不为0报错,相当于出队列
        arrayQueue.remove(0);
        System.out.println("当前队列元素:"+arrayQueue);
    }
}

在这里插入图片描述

ArrayBlockingQueue常用使用方法如下:

在Java中,ArrayBlockingQueue是一个具有固定容量的阻塞队列。它的实现是基于数组的,它实现了BlockingQueue接口,提供了一组方法用于操作队列中的元素。

  1. add(element):向队列尾部添加一个元素,如果队列已满,则IllegalStateExceptio异常。
  2. offer(element):向队列尾部添加一个元素,如果队列已满,则返回false。
  3. put(element):向队列尾部添加一个元素,如果队列已满,则会一直阻塞直到队列有空闲位置。
  4. poll():从队列头部移除并返回一个元素,如果队列为空,则返回null。
  5. take():从队列头部移除并返回一个元素,如果队列为空,则会一直阻塞直到队列有元素可取。
  6. peek():获取队列头部的元素,但不会移除该元素。
  7. size():返回队列中当前元素的数量。
  8. remainingCapacity():返回队列中剩余的可用容量。
  9. isEmpty(): 判断队列是否为空,如果队列为空则返回true,否则返回false。
package com.example.deesign_patterns.test;

import java.util.concurrent.ArrayBlockingQueue;

public class Test3Main {

    public static void main(String[] args) {
        //数组队列使用,必须给数组一个大小,当数组里面的元素数量超过5,就会报错,不能扩容
        ArrayBlockingQueue queue=new ArrayBlockingQueue(5);
        queue.add(1);
        queue.add(2);
        queue.add(3);
        queue.add(4);
        queue.add(5);
        System.out.println("当前队列元素:"+queue);
        System.out.println("当前队列大小:"+queue.size());
        System.out.println("队列已满返回boolean值为:"+queue.offer(6));
        System.out.println("获取队列头部元素:"+queue.peek());
        //出队列
        queue.poll();
        System.out.println("当前队列元素:"+queue);
        System.out.println("当前队列可用容量:"+ queue.remainingCapacity());
    }
}


在这里插入图片描述

LinkedBlockingQueue常用使用方法如下:

LinkedBlockingQueue是一个线程安全的队列,它的实现是基于链表的。LinkedBlockingQueue的容量可以是无限的。

常用使用方法和ArrayBlockingQueue队列方法一样

package com.example.deesign_patterns.test;

import java.util.concurrent.LinkedBlockingQueue;

public class Test3Main {

    public static void main(String[] args) {
        //链表队列使用
        //如果没有给链表一个大小,默认值是Integer.MAX_VALUE
        //LinkedBlockingQueue queue=new LinkedBlockingQueue();
        //如果给链表一个大小,当链表里面的元素数量超过5,就会报错,不能扩容
        LinkedBlockingQueue queue=new LinkedBlockingQueue(5);
        queue.add(1);
        queue.add(2);
        queue.add(3);
        queue.add(4);
        queue.add(5);
        System.out.println("当前队列元素:"+queue);
        System.out.println("当前队列大小:"+queue.size());
        System.out.println("队列已满返回boolean值为:"+queue.offer(6));
        System.out.println("获取队列头部元素:"+queue.peek());
        //出队列
        queue.poll();
        System.out.println("当前队列元素:"+queue);
        System.out.println("当前队列可用容量:"+ queue.remainingCapacity());
    }
}

在这里插入图片描述

ArrayBlockingQueue和LinkedBlockingQueue区别

Java中的ArrayBlockingQueue和LinkedBlockingQueue都是实现了BlockingQueue接口,用于实现多线程环境下的阻塞队列。它们之间的区别主要有以下几个方面:

  1. 数据结构:ArrayBlockingQueue使用数组作为底层数据结构,而LinkedBlockingQueue使用链表作为底层数据结构。这导致了它们在插入和删除操作上的性能特点不同。
  2. 队列大小:ArrayBlockingQueue有一个固定的容量,需要在创建时指定大小,而LinkedBlockingQueue的容量是可选的,默认为Integer.MAX_VALUE。
  3. 线程阻塞:ArrayBlockingQueue在插入和删除元素时,如果队列已满或为空,操作线程会被阻塞,直到有可用的空间或元素可供操作。而LinkedBlockingQueue在插入和删除元素时,如果队列已满或为空,操作线程可以选择被阻塞或立即返回。
  4. 迭代性能:由于LinkedBlockingQueue使用链表作为底层数据结构,迭代操作的性能通常比ArrayBlockingQueue更好。
  5. 吞吐量:在高并发场景下,LinkedBlockingQueue通常比ArrayBlockingQueue具有更好的吞吐量,因为它能够更好地支持并发的插入和删除操作。

综上所述,ArrayBlockingQueue适用于有固定容量要求的场景,操作线程需要在队列满或空时被阻塞;而LinkedBlockingQueue适用于没有固定容量要求的场景,可以更好地支持高并发的插入和删除操作。

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

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

相关文章

Spring-mvc的参数传递与常用注解的解答及页面的跳转方式---综合案例

目录 一.slf4j--日志 二.常用注解 2.1.RequestMapping 2.2.RequestParam 2.3.RequestBody 2.4.PathVariable 三.参数的传递 3.1 基础类型 3.2 复杂类型 3.3 RequestParam 3.4 PathVariable 3.5 RequestBody 3.6 增删改查 四.返回值 4.1 void 返回值 4.2 String 返…

用go实现dns请求

一、DNS报文格式详解 1.1 报文格式 DNS分为查询请求和查询响应&#xff0c;两者的报文结构基本相同。DNS报文格式如下表展示 0 1516 31事务ID&#…

CVE-2023-28303(截图修复)

在做羊城杯的misc的时候发现了一个图片&#xff0c;典型的图片高度不对&#xff0c;修改之后对图片的高度进行不断修改尝试&#xff0c;发现图片很大&#xff0c;但是内容没有出现&#xff0c; 从这里指知道存在feld文件x 截出zip文件内容&#xff0c;把04 03 改为03 04 这里的…

SOLIDWORKS放样是什么意思?

SOLIDWORKS是一款广受欢迎的三维计算机辅助设计&#xff08;CAD&#xff09;软件&#xff0c;提供了许多强大的功能来帮助工程师实现他们的创意。其中一个重要的功能是放样功能&#xff0c;它在设计过程中起着至关重要的作用。本文将介绍SOLIDWORKS放样的概念、特点和应用。 放…

怎么将火狐浏览器中的书签或密码迁移到谷歌浏览器

文章目录 一、点击谷歌浏览器右上角二、选择书签–导入书签和设置…三、点击导入 一、点击谷歌浏览器右上角 二、选择书签–导入书签和设置… 在下拉框中选中Firefox&#xff0c;点击导入 三、点击导入

sublime text 格式化json快捷键配置

以 controlcommandj 为例。 打开Sublime Text&#xff0c;依次点击左上角菜单Sublime Text->Preferences->Key Bindings&#xff0c;出现以下文件&#xff1a; 左边的是Sublime Text默认的快捷键&#xff0c;不可编辑。右边是我们自定义快捷键的地方&#xff0c;在中括号…

手机便签功能在哪里?如何在便签里添加文字图片视频?

手机已成为我们生活中不可或缺的工具&#xff0c;而在使用手机的过程中&#xff0c;我们经常需要随手记录一些重要的事情。那么&#xff0c;如何高效便捷地记录这些事情呢&#xff1f;答案就是使用手机便签软件。但是&#xff0c;有很多人不知道手机便签功能在哪里&#xff1f;…

使用scp在两个linux系统之间传输文件

使用scp在两个linux系统之间传输文件 问题背景拷贝文件首先我们要从源设备&#xff08;本文中是矩池云自己的服务器&#xff09;传输文件至目标设备&#xff08;本文中是A100设备&#xff09;传输一个文件传输一个文件夹 从目标设备&#xff08;本文中是A100设备&#xff09;下…

Python基础之高级函数

异常捕获 Python中&#xff0c;使用trycatch两个关键字来实现对异常的处理。在我们平时的工作中&#xff0c;异常的出现是在所难免的&#xff0c;但是异常一旦出现&#xff0c;极有可能会直接导致程序崩溃&#xff0c;无法正常运行&#xff0c;所以异常一定要及时的做出对应的…

QT(9.5)QT连接OpenCV库完成人脸识别,c语言中的static和c++中的static的用法,在c和c++中const关键字的用法,Qt中基于TCP通信中的服务器和客户端的操作

1.QT完成人脸识别 pro文件: 头文件: #ifndef WIDGET_H #define WIDGET_H#include <QWidget> #include <opencv2/opencv.hpp> #include <iostream> #include <math.h> #include<opencv2/face.hpp> #include <vector> #include <map&g…

【STL】模拟实现map和set {map和set的封装;核心结构;插入和查找;红黑树的迭代器;STL中的红黑树结构}

模拟实现map和set map和set是红黑树的两种不同封装形式&#xff0c;底层使用同一颗泛型结构的红黑树&#xff0c;只是存储类型不同。set是红黑树的K模型&#xff0c;存储key&#xff1b;map是红黑树的KV模型&#xff0c;存储pair<key,value>。 下面的代码和讲解着重体现…

Vue进阶(三十三)Content-Security-Policy(CSP)详解

文章目录 一、前言二、XSS 攻击都有哪些类型&#xff1f;三、CSP介绍3.1 使用HTTP的 Content-Security-Policy头部3.2 使用 meta 标签 四、CSP 实施策略五、Vue中可使用的防XSS攻击方式六、拓展阅读 一、前言 作为前端工程师你真的了解 XSS 吗&#xff1f;越来越多超级应用基于…

预付费电表和断路器的连接方式及注意事项

随着智能电网技术的不断发展&#xff0c;预付费电表已经在我国得到了广泛应用。预付费电表不仅可以实现远程自动抄表、实时监控用电量等功能&#xff0c;还可以有效防止偷电行为&#xff0c;提高用电安全。断路器作为低压配电系统中的重要组成部分&#xff0c;具有保护电路、防…

详细介绍 弹性盒子(display:flex)

文章目录 什么是弹性盒子 如何使用弹性盒子flex系列flex-direction 对齐方向 水平对齐垂直对齐flex-wrap 换行flex-flowflex模型说明容器的属性 justify-content X轴对齐方式align-content Y轴对齐方式总结属性值Y轴对齐的另外一种&#xff1a;align-itemsalign-content和alig…

基于Springboot跟rabbitmq实现的死信队列

概述 RabbitMQ是流行的开源消息队列系统&#xff0c;使用erlang语言开发。为了保证订单业务的消息数据不丢失&#xff0c;需要使用到RabbitMQ的死信队列机制&#xff0c;当消息消费发生异常时&#xff0c;将消息投入死信队列中。但由于对死信队列的概念及配置不熟悉&#xff0…

自然语言处理实战项目17-基于多种NLP模型的诈骗电话识别方法研究与应用实战

大家好&#xff0c;我是微学AI&#xff0c;今天给大家介绍一下自然语言处理实战项目17-基于NLP模型的诈骗电话识别方法研究与应用&#xff0c;相信最近小伙伴都都看过《孤注一掷》这部写实的诈骗电影吧&#xff0c;电影主要围绕跨境网络诈骗展开&#xff0c;电影取材自上万起真…

PPO代码研究(2)

好&#xff0c; 因为我没怎么看懂&#xff0c; 所以我决定再看一遍PPO的代码&#xff0c; 再研究一遍。 事实证明&#xff0c; 重复是一个非常好&#xff0c;非常好的方法。 学习方法。 世界上几乎没有任何新知识是你一遍就能学会的。 你只能学一遍&#xff0c;再来一遍&…

大剧院订座系统源码,大剧院订票,大剧院场馆租赁,大剧院订票系统完整源码

大剧院订座系统源码,大剧院订票&#xff0c;大剧院场馆租赁&#xff0c;大剧院订票系统完整源码 大剧院系统1、管理后台--系统说明2、订票小程序--系统说明3、验票端--系统说明4、系统源码说明 大剧院系统 1、管理后台–系统说明 项目管理&#xff1a;用于创建剧院演出项目 2…

【广州华锐互动】AR技术在配电系统运维中的应用

随着科技的不断发展&#xff0c;AR(增强现实)技术逐渐走进了我们的生活。在电力行业&#xff0c;AR技术的应用也为巡检工作带来了许多新突破&#xff0c;提高了巡检效率和安全性。本文将从以下几个方面探讨AR配电系统运维系统的新突破。 首先&#xff0c;AR技术可以实现虚拟巡检…

Qt应用开发(基础篇)——按钮基类 QAbstractButton

一、前言 QAbstractButton类&#xff0c;继承于QWidget&#xff0c;是Qt按钮小部件的抽象基类&#xff0c;提供按钮常用的功能。 QAbstractButton按钮基类&#xff0c;它的子类(pushbutton、checkbox、toolbutton等)处理用户操作&#xff0c;并指定按钮的绘制方式。QAbstractBu…