PriorityQueue即优先队列(优先队列的作用是保证每次取出的都是队列中权值最小的元素,Java中每次取最小元素)是基于优先级堆产生的无界队列,他的元素排序是按照自然排序来进行排序的,在创建时可以给他添加一个给元素排序的比较器,不能存储null值。PriorityQueue是线程不安全的,时间复杂度是O(log(n)) (在入队和出队时)
PriorityQueue实现了Queue接口,不允许放入
null
元素,其通过堆实现,具体说是通过完全二叉树(complete binary tree)实现的小顶堆(任意一个非叶子节点的权值,都不大于其左右子节点的权值)
add(E e)和offer(E e)都是向优先队列中插入元素:
add(E e)插入失败会抛出异常
offer(E e)插入失败会返回false
插入元素可能会破坏小顶堆的性质,因此需要必要的调整,具体如下:
先调用扩容函数grow()就是在申请一个更大的数组,把原数组复制过去,通过siftUp(int k,E x)维持堆的特性(从
k
指定的位置开始,将x
逐层与当前点的parent
进行比较并交换,直到满足x >= queue[parent]
为止)
element()和peek()都是获取队列首个元素但不删除(也就是队列中权值最小的那个元素):
element()获取失败会抛出异常
peek()获取失败会返回null
remove()和poll()都是获取并删除队首元素:
remove()失败抛出异常
poll()失败返回null
由于删除操作会改变队列的结构,为维护小顶堆的性质,需要进行必要的调整:首先记录0
下标处的元素,并用最后一个元素替换0
下标位置的元素,之后调用siftDown()
方法对堆进行调整,最后返回原来0
下标处的那个元素(也就是最小的那个元素)。重点是siftDown(int k, E x)
方法,该方法的作用是从k
指定的位置开始,将x
逐层向下与当前点的左右孩子中较小的那个交换,直到x
小于或等于左右孩子中的任何一个为止。