Java - 优先级队列(PriorityQueue)

优先级队列 

队列是一种先进先出(FIFO)的数据结构,但是有些情况下,操作的数据可能带有优先级,一般出队列时,可能需要优先级高的元素先出队列,在这种情况下使用队列就不行了

在这种情况下,我们的数据结构应该提供两个最基本的操作,一个是返回最高优先级对象,一个是添加新对象,这种数据结构就是优先级队列(PriorityQueue)

PriorityQueue 的底层是堆,堆的底层是数组

Java集合框架中提供了PriorityQueuePriorityBlockingQueue两种类型的优先级队列,PriorityQueue是线程不安全的,PriorityBlockingQueue是线程安全的,这里主要使用PriorityQueue。


什么是堆

堆其实就是一棵完全二叉树,它的底层是一个数组,数组中存储这棵完全二叉树层序遍历的结果,按种类分,它又分为大根堆和小根堆

堆的基本作用是快速找到集合中的最值


PriorityQueue

PriorityQueue中放置的元素必须要能够比较大小 (只有实现了 Comparable 和 Comparator 接口的类才能比较大小),不能插入无法比较大小的对象,否则会抛出 ClassCastException 异常

不能插入 null 对象,否则会抛出 NullPointerException 异常

没有容量限制,可以插入任意多个元素,其内部可以自动扩容

PriorityQueue底层使用了堆数据结构

PriorityQueue 默认情况下是小堆 --- 即每次获取到的元素都是最小的元素

如果要转换成大堆需要用户提供比较器:

PriorityQueue<Integer> queue = new PriorityQueue<Integer>(new Comparator<Integer>() {
    public int compare(Integer num1, Integer num2) {
        return num2 - num1;
    }
});

构造方法

  • PriorityQueue()
  • 创建一个具有默认初始容量(11)的优先队列,该队列根据元素的自然顺序对其元素进行排序。
  • PriorityQueue(int initialCapacity)
  • 创建一个具有指定初始容量的优先队列,根据元素的自然顺序对元素进行排序。
  • PriorityQueue(Collection<? extends E> c)
  • 创建一个优先级队列,包含指定集合中的元素。如果指定的集合是 SortedSet 的实例,或者是另一个优先级队列,则此优先级队列将按照相同的顺序排序。否则,此优先级队列将根据其元素的自然顺序进行排序。
  • PriorityQueue(Comparator<? super E> comparator)
  • 使用默认的初始容量创建一个优先级队列,其元素根据指定的比较器进行排序。

操作方法

boolean offer(E e)    插入元素 e,插入成功返回 true,如果 e 对象为空,抛出 NullPointerException 异常,时间复杂度为 O(log2N) ,注意:空间不够时会自动扩容
E peek()    获取优先级最高的元素,如果优先级队列为空,返回 null
E poll()    移除优先级最高的元素并返回,如果优先级队列为空,返回 null
int size()    获取有效元素的个数
void clean()    清空
boolean isEmpty()    检测优先级队列是否为空,空返回 true

扩容

private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
    private void grow(int minCapacity) {
        int oldCapacity = queue.length;
        
        int newCapacity = oldCapacity + ((oldCapacity < 64) ? (oldCapacity + 2): (oldCapacity >> 1));

        if (newCapacity - MAX_ARRAY_SIZE > 0) {
            newCapacity = hugeCapacity(minCapacity);
        }

        queue = Arrays.copyOf(queue,newCapacity);
    }
  • 如果容量 < 64,按照 oldCapacity * 2 + 2 进行扩容
  • 如果容量 >= 64,按照 oldCapacity * 1.5 进行扩容
  • 如果容量超过 MAX_ARRAY_SIZE,按照 MAX_ARRAY_SIZE 进行扩容
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值