Java-Deque

ArrayDeque

  • 栈和队列
    Deque的含义是“double ended queue”,即双端队列,它既可以当作栈使⽤,也可以当作队列使⽤。下表列出了Deque与Queue相对应的接⼝:
    Queue Method Equivalent Deque Method 说明
    add(e) addLast(e) 向队尾插⼊元素,失败则抛出异常
    offer(e) offerLast(e) 向队尾插⼊元素,失败则返回 false
    remove() removeFirst() 获取并删除队⾸元素,失败则抛出异常
    poll() pollFirst() 获取并删除队⾸元素,失败则返回 null
    element() getFirst() 获取但不删除队⾸元素,失败则抛出异常
    peek() peekFirst() 获取但不删除队⾸元素,失败则返回 null
    Stack Method Equivalent Deque Method 说明
    push(e) addFirst(e) 向栈顶插⼊元素,失败则抛出异常
    ⽆ offerFirst(e) 向栈顶插⼊元素,失败则返回 false
    pop() removeFirst() 获取并删除栈顶元素,失败则抛出异常
    ⽆ pollFirst() 获取并删除栈顶元素,失败则返回 null
    peek() getFirst() 获取但不删除栈顶元素,失败则抛出异常
    ⽆ peekFirst() 获取但不删除栈顶元素,失败则返回 null

  • ArrayDeque是⾮线程安全的(not thread-safe),当多个线程同时使⽤的时候,需要⼿动同步;另外,该容器不允许放⼊ null 元素。

  • add
    在这里插入图片描述
    head head 指向⾸端第⼀个有效元素, tail tail 指向尾端第⼀个可以插⼊元素的空
    位。因为是循环数组,所以 head 不⼀定总等于 0, tail 也不⼀定总是⽐ head ⼤。
    在这里插入图片描述

  • doubleCapacity()
    在这里插入图片描述
    在这里插入图片描述

  • 总结
    当需要实现先进先出(FIFO)或者先进后出(LIFO)的数据结构时,可以考虑使⽤ ArrayDeque。以下是⼀些使⽤ ArrayDeque 的场景:
    管理任务队列:如果需要实现⼀个任务队列,可以使⽤ ArrayDeque 来存储任务元素。在队列头部添加新任务元素,从队列尾部取出任务进⾏处理,可以保证任务按照先进先出的顺序执⾏。
    实现栈:ArrayDeque 可以作为栈的实现⽅式,⽀持 push、pop、peek 等操作,可以⽤于需要后进先出的场景。
    实现缓存:在需要缓存⼀定数ᰁ的数据时,可以使⽤ ArrayDeque。当缓存的数据超过容量时,可以从队列头部删除最⽼的数据,从队列尾部添加新的数据。
    实现事件处理器:ArrayDeque 可以作为事件处理器的实现⽅式,⽀持从队列头部获取事件进⾏处理,从队列尾部添加新的事件。

ArrayDeque 是 Java 标准库中的⼀种双端队列实现,底层基于数组实现。与 LinkedList 相⽐,ArrayDeque 的性能更优,因为它使⽤连续的内存空间存储元素,可以更好地利⽤ CPU 缓存,在⼤多数情况下也更快。
因为ArrayDeque 的底层实现是数组,⽽ LinkedList 的底层实现是链表。数组是⼀段连续的内存空间,⽽链表是由多个节点组成的,每个节点存储数据和指向下⼀个节点的指针。因此,在使⽤LinkedList 时,需要频繁进⾏内存分配和释放,⽽ ArrayDeque 在创建时就⼀次性分配了连续的内存空间,不需要频繁进⾏内存分配和释放,这样可以更好地利⽤ CPU 缓存,提⾼访问效率。
现代计算机CPU对于数据的局部性有很强的依赖,如果需要访问的数据在内存中是连续存储的,那么就可以利⽤CPU的缓存机制,提⾼访问效率。⽽当数据存储在不同的内存块⾥时,每次访问都需要从内存中读取,效率会受到影响。
当然了,使⽤ ArrayDeque 时,数组复制操作也是需要考虑的性能消耗之⼀。
当 ArrayDeque 的元素数量超过了初始容量时,会触发扩容操作。扩容操作会创建⼀个新的数组,并将原有元素复制到新数组中。扩容操作的时间复杂度为 O(n)。不过,ArrayDeque 的扩容策略(当 ArrayDeque 中的元素数ᰁ达到数组容ᰁ时,就需要进⾏扩容操作,扩容时会将数组容ᰁ扩⼤为原来的两倍)可以在⼀定程度上减少数组复制的次数和时间消耗,同时保证 ArrayDeque 的性能和空间利⽤率。
ArrayDeque 不仅⽀持常⻅的队列操作,如添加元素、删除元素、获取队列头部元素、获取队列尾部元素等。同时,它还⽀持栈操作,如 push、pop、peek 等。这使得 ArrayDeque 成为⼀种⾮常灵活的数据结构,可以⽤于各种场景的数据存储和处理。

PriorityDeque

在 PriorityQueue 中,每个元素都有⼀个优先级,这个优先级决定了元素在队列中的位置。队列内部通过⼩顶堆(也可以是⼤顶堆)的⽅式来维护元素的优先级关系。
具体来说,⼩顶堆是⼀个完全⼆叉树,任何⼀个⾮叶⼦节点的权值,都不⼤于其左右⼦节点的权值,这样保证了队列的顶部元素(堆顶)⼀定是优先级最⾼的元素。
完全⼆叉树(Complete Binary Tree)是⼀种⼆叉树,其中除了最后⼀层,其他层的节点数都是满的,最后⼀层的节点都靠左对⻬.
堆是⼀种完全⼆叉树,堆的特点是根节点的值最⼩(⼩顶堆)或最⼤(⼤顶堆),并且任意⾮根节点i的值都不⼤于(或不⼩于)其⽗节点的值。

  • 节点关系
    在这里插入图片描述
  • 添加元素
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    调整的过程为:从 kk 指定的位置开始,将 xx 逐层与当前点的 parent parent 进⾏⽐较并交换,直到满⾜ x >= queue[parent] x >= queue[parent] 为⽌。注意这⾥的⽐较可以是元素的⾃然顺序,也可以是依靠⽐较器的顺序
  • element()和 peek()
  • remove()和 poll()
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    remove(Object o) 可以分为 2 种情况:
  1. 删除的是最后⼀个元素。直接删除即可,不需要调整。
  2. 删除的不是最后⼀个元素,从删除点开始以最后⼀个元素为参照调⽤⼀次 siftDown() 即可
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
  • 总结
    PriorityQueue 是⼀个⾮常常⽤的数据结构,它是⼀种特殊的堆(Heap)实现,可以⽤来⾼效地维护⼀个有序的集合。
    它的底层实现是⼀个数组,通过堆的性质来维护元素的顺序。
    取出元素时按照优先级顺序(从⼩到⼤或者从⼤到⼩)进⾏取出。
    如果需要指定排序,元素必须实现 Comparable 接⼝或者传⼊⼀个 Comparator 来进⾏⽐较。
Java中的Queue和Deque是两种不同的数据结构。 1. Queue(单向队列)是一种FIFO(先进先出)的数据结构,它继承自Collection接口。Queue有一个直接子类PriorityQueue,它是一个基于优先级的队列,元素按照优先级进行排序。Queue的常用方法包括add()、offer()、remove()、poll()、element()和peek()等。 2. Deque(双向队列)是一种支持在两端添加或移除元素的数据结构,它继承自Queue接口。Deque有两个直接子类:LinkedList和ArrayDeque。LinkedList是基于链表实现的双向队列,而ArrayDeque是基于数组实现的双向队列。Deque的常用方法包括addFirst()、addLast()、offerFirst()、offerLast()、removeFirst()、removeLast()、pollFirst()、pollLast()、getFirst()、getLast()、peekFirst()和peekLast()等。 以下是Java中使用Queue和Deque的示例代码: ```java import java.util.Queue; import java.util.LinkedList; import java.util.ArrayDeque; public class QueueDequeExample { public static void main(String[] args) { // 使用Queue Queue<String> queue = new LinkedList<>(); queue.add("apple"); queue.add("banana"); queue.add("orange"); System.out.println("Queue: " + queue); System.out.println("First element: " + queue.peek()); System.out.println("Removed element: " + queue.poll()); System.out.println("Queue after removal: " + queue); // 使用Deque Deque<Integer> deque = new ArrayDeque<>(); deque.addFirst(1); deque.addLast(2); deque.addLast(3); System.out.println("Deque: " + deque); System.out.println("First element: " + deque.getFirst()); System.out.println("Last element: " + deque.getLast()); System.out.println("Removed first element: " + deque.removeFirst()); System.out.println("Deque after removal: " + deque); } } ```
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值