iis服务器助手广告广告
返回顶部
首页 > 资讯 > 后端开发 > JAVA >Java 数据结构之队列(Queue)详解
  • 488
分享到

Java 数据结构之队列(Queue)详解

java队列Queue接口Deque接口 2023-10-12 14:10:03 488人浏览 安东尼
摘要

目录 1、在Java中有哪些常见的队列? 2、Queue 接口分析 3、Deque 接口分析 4、PriorityQueue 的实现原理详解 5、使用Java数组实现队列的简单示例 1、在Java中有哪些常见的队列?         在

目录

1、在Java中有哪些常见的队列?

2、Queue 接口分析

3、Deque 接口分析

4、PriorityQueue 的实现原理详解

5、使用Java数组实现队列的简单示例


1、在Java中有哪些常见的队列?

        在Java中,有一些常见的队列实现。下面是其中一些的列举://队列也是一种线性的数据结构

  1. ArrayList:ArrayList可以被用作队列,通过在列表末尾添加元素,并使用remove(0)方法从列表的开头删除元素。但是,由于在列表的开头删除元素会导致后续元素的移动,因此对于大量的插入和删除操作来说,ArrayList的性能可能不是最佳选择。
  2. LinkedList:LinkedList也可以用作队列。LinkedList实现了Queue接口,可以使用offer()方法在队列的末尾添加元素,使用poll()方法从队列的开头删除并返回元素。LinkedList对于插入和删除操作具有较好的性能,因为它使用了指针来链接元素,而不需要移动其他元素。
  3. ArrayBlockingQueue:ArrayBlockingQueue是一个有界阻塞队列,底层使用数组实现。它有一个固定的容量,并且在插入或删除元素时可能会阻塞线程,直到满足特定的条件。
  4. LinkedBlockingQueue:LinkedBlockingQueue是一个可选有界或无界的阻塞队列,底层使用链表实现。它具有类似于ArrayBlockingQueue的功能,但在内部实现上略有不同。
  5. PriorityBlockingQueue:PriorityBlockingQueue是一个支持优先级的无界阻塞队列。元素按照它们的优先级顺序被插入和删除。
  6. ConcurrentLinkedQueue:ConcurrentLinkedQueue是一个非阻塞无界队列,它适用于多线程环境。它使用链表实现,并且提供了高效的并发操作。

        以上是Java中的一些常见队列实现。具体选择哪种队列取决于你的需求和使用场景。

2、Queue 接口分析

        Queue接口是Java集合框架中定义的一个接口,它代表了一个先进先出(FIFO)的队列。Queue接口继承自Collection接口,它定义了一组方法来操作队列中的元素。下面是Queue接口的一些主要方法和特性的详细解释:

(1)添加元素:

  1. boolean add(E element): 将指定的元素添加到队列的末尾,如果成功则返回true,如果队列已满则抛出异常。
  2. boolean offer(E element): 将指定的元素添加到队列的末尾,如果成功则返回true,如果队列已满则返回false。

(2)移除元素:

  1. E remove(): 移除并返回队列头部的元素,如果队列为空则抛出异常。
  2. E poll(): 移除并返回队列头部的元素,如果队列为空则返回null。

(3)获取头部元素:

  1. E element(): 获取队列头部的元素,但不移除它,如果队列为空则抛出异常。
  2. E peek(): 获取队列头部的元素,但不移除它,如果队列为空则返回null。

(4)队列大小:

  1. int size(): 返回队列中的元素个数。
  2. boolean isEmpty(): 判断队列是否为空。

        Queue接口还有一些其他方法,如clear()用于清空队列中的所有元素contains(Object o)用于判断队列是否包含指定元素等。

        Queue接口的常见实现类包括LinkedList、ArrayDequePriorityQueue等。LinkedList实现了Queue接口,并且还可以作为栈使用,它是一个双向链表。ArrayDeque是一个双端队列,它同时实现了Queue和Deque接口。PriorityQueue是一个基于优先级的队列,它允许元素按照优先级顺序被插入和删除。

        通过使用Queue接口,我们可以方便地进行队列操作,如入队、出队、查看队列头部元素等。它在处理任务调度、消息传递等场景中非常有用

        Java Queue接口使用示例:

        当使用Java中的Queue接口时,我们需要选择具体的实现类来创建一个队列对象。下面是一个使用Queue接口的示例,以LinkedList实现类为例:

import java.util.Queue;import java.util.LinkedList;public class QueueExample {    public static void main(String[] args) {        // 创建一个Queue对象        Queue queue = new LinkedList<>();        // 添加元素到队列        queue.add("Apple");        queue.add("Banana");        queue.add("Orange");        // 获取队列头部元素        String head = queue.peek();        System.out.println("头部元素:" + head);        // 遍历队列并输出元素        System.out.println("队列元素:");        for (String element : queue) {            System.out.println(element);        }        // 移除队列头部元素        String removedElement = queue.remove();        System.out.println("移除的元素:" + removedElement);        // 队列大小        int size = queue.size();        System.out.println("队列大小:" + size);        // 判断队列是否为空        boolean isEmpty = queue.isEmpty();        System.out.println("队列是否为空:" + isEmpty);    }}

        在这个示例中,我们使用LinkedList作为实现类创建了一个Queue对象。我们向队列中添加了三个元素:"Apple","Banana"和"Orange"。然后,我们使用peek()方法获取队列的头部元素,并使用for-each循环遍历队列并输出每个元素。

        接下来,我们使用remove()方法移除队列的头部元素,并使用size()方法获取队列的大小。最后,我们使用isEmpty()方法判断队列是否为空。

3、Deque 接口分析

        Deque接口是Java集合框架中定义的一个接口,它代表了一个双端队列(Double Ended Queue)。Deque是"双端队列"的缩写。Deque接口继承自Queue接口,并在其基础上提供了在队列两端进行添加、删除和检索元素的操作。Deque可以在队列的头部和尾部同时进行元素的插入和删除,因此可以作为队列、栈或双向队列使用。

        Deque接口定义了以下主要方法和特性:

(1)添加元素:

  1. void addFirst(E element): 将指定元素添加到双端队列的头部。
  2. void addLast(E element): 将指定元素添加到双端队列的尾部。
  3. boolean offerFirst(E element): 将指定元素添加到双端队列的头部,如果成功则返回true,如果队列已满则返回false。
  4. boolean offerLast(E element): 将指定元素添加到双端队列的尾部,如果成功则返回true,如果队列已满则返回false。

(2)移除元素:

  1. E removeFirst(): 移除并返回双端队列的头部元素,如果队列为空则抛出异常。
  2. E removeLast(): 移除并返回双端队列的尾部元素,如果队列为空则抛出异常。
  3. E pollFirst(): 移除并返回双端队列的头部元素,如果队列为空则返回null。
  4. E pollLast(): 移除并返回双端队列的尾部元素,如果队列为空则返回null。

(3)获取头部和尾部元素:

  1. E getFirst(): 获取双端队列的头部元素,但不移除它,如果队列为空则抛出异常。
  2. E getLast(): 获取双端队列的尾部元素,但不移除它,如果队列为空则抛出异常。
  3. E peekFirst(): 获取双端队列的头部元素,但不移除它,如果队列为空则返回null。
  4. E peekLast(): 获取双端队列的尾部元素,但不移除它,如果队列为空则返回null。

        Deque接口还提供了一些其他方法,如size()用于返回双端队列中的元素个数,isEmpty()用于判断双端队列是否为空,clear()用于清空双端队列中的所有元素等。

        Deque接口的常见实现类包括ArrayDeque和LinkedList。ArrayDeque是一个基于数组实现的双端队列,支持高效的随机访问和动态扩展。LinkedList是一个基于链表实现的双端队列,支持高效的插入和删除操作。

        通过使用Deque接口,我们可以方便地进行双端队列操作,如在队列的头部和尾部插入和删除元素,获取头部和尾部元素,以及判断队列是否为空。Deque在许多场景下都很有用,比如实现LRU缓存、实现任务调度等

        另外,需要注意的是,Deque接口还可以用作栈(LIFO)的数据结构。通过在队列头部执行插入和删除操作,可以实现栈的功能。常见的栈操作可以使用Deque接口中的以下方法来实现:

  1. void push(E element): 将元素推入栈顶,等同于addFirst(E element)。
  2. E pop(): 弹出并返回栈顶元素,等同于removeFirst()。
  3. E peek(): 获取栈顶元素,等同于peekFirst()。

        所以,Deque接口是一个非常有用的接口,提供了双端队列的功能,既可以在队列的头部进行操作,也可以在尾部进行操作。它是Queue接口的扩展,可以方便地实现队列、栈和双向队列的功能,并提供了丰富的方法来操作和访问队列中的元素。

        Java Deque 接口使用示例

        当使用Java中的Deque接口时,我们同样需要选择具体的实现类来创建一个双端队列对象。下面是一个使用Deque接口的示例,以ArrayDeque实现类为例:

import java.util.Deque;import java.util.ArrayDeque;public class DequeExample {    public static void main(String[] args) {        // 创建一个Deque对象        Deque deque = new ArrayDeque<>();        // 添加元素到双端队列        deque.addFirst("Apple");        deque.addLast("Banana");        deque.addLast("Orange");        // 获取双端队列头部和尾部元素        String first = deque.getFirst();        String last = deque.getLast();        System.out.println("头部元素:" + first);        System.out.println("尾部元素:" + last);        // 遍历双端队列并输出元素        System.out.println("双端队列元素(从头到尾):");        for (String element : deque) {            System.out.println(element);        }        // 移除双端队列头部和尾部元素        String removedFirst = deque.removeFirst();        String removedLast = deque.removeLast();        System.out.println("移除的头部元素:" + removedFirst);        System.out.println("移除的尾部元素:" + removedLast);        // 双端队列大小        int size = deque.size();        System.out.println("双端队列大小:" + size);        // 判断双端队列是否为空        boolean isEmpty = deque.isEmpty();        System.out.println("双端队列是否为空:" + isEmpty);    }}

        在这个示例中,我们使用ArrayDeque作为实现类创建了一个Deque对象。我们向双端队列中添加了三个元素:"Apple"、"Banana"和"Orange"。然后,我们使用getFirst()和getLast()方法分别获取双端队列的头部和尾部元素,并使用for-each循环遍历双端队列并输出每个元素。

        接下来,我们使用removeFirst()和removeLast()方法移除双端队列的头部和尾部元素,并使用size()方法获取双端队列的大小。最后,我们使用isEmpty()方法判断双端队列是否为空。

4、PriorityQueue 的实现原理详解

        PriorityQueue的实现原理是基于二叉堆(Binary Heap),它是一种特殊的完全二叉树结构,具有以下性质:

  • 最小堆性质:在最小堆中,每个节点的值都小于或等于其子节点的值。也就是说,堆的根节点是最小的元素。

        PriorityQueue使用一个数组来存储元素,并通过二叉堆的形式来组织这些元素。数组中的元素按照特定的顺序排列,满足最小堆的性质。在数组中,根节点位于索引0处,而对于任意位置i的节点,它的左子节点位于索引2i+1处,右子节点位于索引2i+2处。

        当元素被添加到PriorityQueue时,它会被放置在数组的末尾,并按照以下步骤进行调整,以维护最小堆的性质:

  • 上滤(Up-Heap)操作:新插入的元素会与其父节点进行比较。如果新插入的元素的优先级比父节点的优先级低(或者更大),则它会与父节点进行交换,直到满足最小堆的性质。

        当从PriorityQueue中删除元素时,队列头部的元素被移除,并将数组的最后一个元素移动到头部位置。然后,这个元素会与其子节点进行比较,以保持最小堆的性质。

  • 下滤(Down-Heap)操作:被移动到头部位置的元素会与其子节点进行比较。如果它的优先级比其中一个或两个子节点的优先级高(或者更小),则它会与较小的子节点进行交换。这个过程会递归地向下进行,直到满足最小堆的性质。

        通过上述的上滤和下滤操作,PriorityQueue可以保持最小堆的性质,使得具有最高优先级的元素总是位于队列的头部。

        PriorityQueue的插入和删除操作的时间复杂度都是O(logN),其中N是队列中的元素个数。这是因为这些操作涉及到堆的调整,需要按照树的高度来进行操作。同时,PriorityQueue还支持高效的查找具有最高优先级的元素,时间复杂度为O(1)。

        需要注意的是,PriorityQueue允许元素具有相同的优先级,但它们的顺序不一定是确定的。在这种情况下,PriorityQueue的行为是不保证的,具有相同优先级的元素可能会以任意顺序被取出

        优先队列(PriorityQueue)的使用示例:

    public static void main(String[] args) {        //默认采用的是最小堆实现的        PriorityQueue queue = new PriorityQueue(10, new Comparator() {            public int compare(Integer a, Integer b) {                return a - b; //if a>b 则交换,so这是递增序列            }        });        queue.offer(13);        queue.offer(9);        int len = queue.size();        for (int i = 0; i < len; i++) {            System.out.println(queue.poll());        }        //输出 9  13        //默认采用的是最小堆实现的        PriorityQueue queue2 = new PriorityQueue<>(10);        queue2.offer(11);        queue2.offer(9);        len = queue2.size();        for (int i = 0; i < len; i++) {            System.out.println(queue2.poll());        }        //输出 9, 11    }

5、使用Java数组实现队列的简单示例

        下面是使用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 enqueue(int item) {        if (isFull()) {            System.out.println("Queue is full. Cannot enqueue.");            return;        }        rear = (rear + 1) % capacity; // 循环队列,计算新的尾部位置        queue[rear] = item;        size++;        System.out.println("Enqueued: " + item);    }    public int dequeue() {        if (isEmpty()) {            System.out.println("Queue is empty. Cannot dequeue.");            return -1;        }        int item = queue[front];        front = (front + 1) % capacity; // 循环队列,计算新的头部位置        size--;        System.out.println("Dequeued: " + item);        return item;    }    public int peek() {        if (isEmpty()) {            System.out.println("Queue is empty.");            return -1;        }        return queue[front];    }    public void display() {        if (isEmpty()) {            System.out.println("Queue is empty.");            return;        }        System.out.print("Queue: ");        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.enqueue(10);        queue.enqueue(20);        queue.enqueue(30);        queue.display(); // Queue: 10 20 30        queue.dequeue();        queue.display(); // Queue: 20 30        queue.enqueue(40);        queue.enqueue(50);        queue.display(); // Queue: 20 30 40 50        queue.dequeue();        queue.dequeue();        queue.display(); // Queue: 40 50    }}

        以上示例演示了使用Java数组实现的简单队列(循环队列)。通过enqueue()方法将元素入队,dequeue()方法将元素出队,peek()方法返回队列头部元素,size()方法返回队列当前元素个数,isEmpty()方法和isFull()方法检查队列是否为空或已满。display()方法用于打印队列中的元素。

        上述循环队列实现的具体步骤总结如下:

(1)入队操作(enqueue):

  1. 首先,检查队列是否已满(isFull()方法)。如果已满,则无法入队,并输出相应的提示信息。
  2. 否则,计算新的尾部位置(rear = (rear + 1) % capacity),并将新元素存储到该位置。
  3. 增加队列的元素个数(size++)。
  4. 输出入队的元素信息。

(2)出队操作(dequeue):

  1. 首先,检查队列是否为空(isEmpty()方法)。如果为空,则无法出队,并输出相应的提示信息。
  2. 否则,获取头部元素(queue[front])并保存到临时变量中。
  3. 计算新的头部位置(front = (front + 1) % capacity)
  4. 减少队列的元素个数(size--)。
  5. 输出出队的元素信息,并返回该元素的值。

(3)查看头部元素(peek):

  1. 首先,检查队列是否为空(isEmpty()方法)。如果为空,则输出相应的提示信息并返回特定的值(如-1)。
  2. 否则,返回头部元素(queue[front])的值。

(4)判断队列是否为空(isEmpty):

  • 根据队列的元素个数(size)是否为0来判断队列是否为空。

(5)判断队列是否已满(isFull):

  • 根据队列的元素个数(size)是否等于队列的容量(capacity)来判断队列是否已满。

(6)遍历打印队列中的元素(display):

  1. 首先,检查队列是否为空(isEmpty()方法)。如果为空,则输出相应的提示信息。
  2. 否则,从头部位置(front)开始循环遍历队列中的元素,依次输出每个元素。
  3. 注意使用循环变量(index)进行索引,并通过取余运算实现循环遍历

        这样,通过以上实现,我们可以使用Java数组来创建一个简单的队列,并进行入队、出队、查看头部元素以及遍历打印等操作。这种基于数组的实现方式可以满足队列的基本需求,并且具有较好的性能。但需要注意的是,由于数组的容量是固定的,当队列已满时,无法再添加新的元素,除非进行元素的出队操作。

来源地址:https://blog.csdn.net/swadian2008/article/details/126783574

--结束END--

本文标题: Java 数据结构之队列(Queue)详解

本文链接: https://www.lsjlt.com/news/429459.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • Java 数据结构之队列(Queue)详解
    目录 1、在Java中有哪些常见的队列? 2、Queue 接口分析 3、Deque 接口分析 4、PriorityQueue 的实现原理详解 5、使用Java数组实现队列的简单示例 1、在Java中有哪些常见的队列?         在...
    99+
    2023-10-12
    java 队列 Queue 接口 Deque 接口
  • 详解python数据结构之队列Queue
    目录一、前言二、Queue的基本格式三、入队列函数 en_queue四、删除数据函数 de_queue一、前言 队列Queue是一种先进先出(FIFO,First In First ...
    99+
    2022-11-12
  • java实现队列queue数据结构详解
    目录概念队列中两个主要操作队列遵循以下条件:队列的数组实现总结概念 队列是一种非原始(特殊)的线性表,是一种先进先出(FIFO)的数据结构。它只允许在表的前端(front)进行删除操...
    99+
    2022-11-13
  • Python数据结构之优先级队列queue用法详解
    目录一、基本用法二、LIFO队列三、优先队列一、基本用法 Queue类实现了一个基本的先进先出容器。使用put()将元素增加到这个序列的一端,使用get()从另一端删除。具体代码如下...
    99+
    2022-11-12
  • c语言数据结构之栈和队列详解(Stack&Queue)
    目录简介栈一、栈的基本概念1、栈的定义2、栈的常见基本操作二、栈的顺序存储结构1、栈的顺序存储2、顺序栈的基本算法3、共享栈(两栈共享空间)三、栈的链式存储结构1、链栈2、链栈的基本...
    99+
    2022-11-13
  • JS数据结构之队列结构详解
    目录一.认识队列二.队列的应用三.队列类的创建四.队列的常见操作五.击鼓传花六.优先级队列七.优先级队列的实现一.认识队列 受限的线性结构: 我们已经学习了一种受限的线性结构:栈结构...
    99+
    2022-11-13
    JS队列结构 JS队列 JS 数据结构
  • TypeScript数据结构之队列结构Queue教程示例
    目录1. 认识队列结构2. 实现队列结构封装3. 实战一:最近的请求次数3.1 题目描述3.2 解一:队列4. 实战二:无法吃午餐的学生数量4.1 题目描述4.2 解一:队列5. 实...
    99+
    2023-02-05
    TypeScript 队列结构 TypeScript Queue
  • Python数据结构之队列详解
    目录0. 学习目标1. 队列的基本概念1.1 队列的基本概念1.2 队列抽象数据类型1.3 队列的应用场景2. 队列的实现2.1 顺序队列的实现2.2 链队列的实现2.3 队列的不同...
    99+
    2022-11-13
  • Java数据结构之堆(优先队列)详解
    目录堆的性质堆的分类堆的向下调整堆的建立堆得向上调整堆的常用操作入队列出队列获取队首元素TopK 问题例子数组排序堆的性质 堆逻辑上是一棵完全二叉树,堆物理上是保存在数组中 。 总...
    99+
    2022-11-13
  • java如何实现队列queue数据结构
    这篇文章主要介绍java如何实现队列queue数据结构,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!概念队列是一种非原始(特殊)的线性表,是一种先进先出(FIFO)的数据结构。它只允许在表的前端(front)进行删除...
    99+
    2023-06-29
  • Java数据结构之栈与队列实例详解
    目录一,栈1,概念2,栈的操作3,栈的实现 4,实现mystack二,队列1,概念 2,队列的实现 3,实现myqueue栈、队列与数组的区别?总结 一,栈 1,概念 在我们软件应用...
    99+
    2022-11-12
  • JAVA队列( Queue ) 详解
    队列(Queue)是一种常见的数据结构,它遵循先进先出(First-In-First-Out,FIFO)的原则。在队列中,新元素插入...
    99+
    2023-09-15
    Java
  • 数据结构TypeScript之栈和队列详解
    目录栈结构特点出栈和入栈面向对象方法封装栈队列结构特点出队和入队面向对象方法封装队列栈结构特点 栈是线性表的其中一种,用于存储固定顺序的元素,元素增删具有先进后出的特点。 出栈和入...
    99+
    2023-01-30
    TypeScript数据结构栈队列 TypeScript数据结构
  • Javascript数据结构之栈和队列详解
    目录前言栈(stack)栈实现解决实际问题栈的另外应用简单队列(Queue)队列实现队列应用 - 树的广度优先搜索(breadth-first search,BFS)优先队列优先队列...
    99+
    2022-11-13
  • java 数据结构之栈与队列
    java 数据结构之栈与队列一:对列队列是一种先进先出的数据结构实现代码:package Queue; public class Queue { //队列类 private int maxSize; //定义队列的长度 ...
    99+
    2023-05-31
    java 队列
  • JavaScript队列数据结构详解
    目录什么是队列?JavaScript中的队列JavaScript中的应用场景最近的请求次数补充总结写在前面: 在上一篇文章中介绍了栈这个数据结构,这篇文章介绍一下队列。 什么是队列?...
    99+
    2022-11-13
  • Java数据结构之优先级队列(堆)图文详解
    目录一、堆的概念二、向下调整1.建初堆2.建堆三、优先级队列1.什么是优先队列?2.入队列3.出队列4.返回队首元素5.堆的其他TopK问题总结:总结一、堆的概念 堆的定义:n个元素...
    99+
    2022-11-13
  • Java数据结构之优先级队列(PriorityQueue)用法详解
    目录概念PriorityQueue的使用小试牛刀(最小k个数) 堆的介绍优先级队列的模拟实现Top-k问题概念 优先级队列是一种先进先出(FIFO)的数据结构,与队列不同的...
    99+
    2022-11-13
  • Java深入了解数据结构之栈与队列的详解
    目录一,栈1,概念2,栈的操作3,栈的实现①入栈②出栈③获取栈顶元素④判断栈是否为空 4,实现mystack二,队列1,概念2,队列的实现①入队②出队③获取队首元素3,实现...
    99+
    2022-11-13
  • java数据结构之队列的入队和出队
    用java实现队列的入队出队首先要定义几个变量与数组:a:表示队列的数组 (推荐学习:java课程)rear:表示队列尾,这里初始化为0(入队一个元素下标就往后移动一位)front:表示队列头,同样初始化为0(出队一...
    99+
    2016-04-08
    java教程 java
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作