8月20日,终于判了,但有失公正,社会可以不公平但不能不公正--写在正文前的废话。
PriorityQueue这个东西叫啥,随便反正我不会翻译她,我只想把我N年前看过的目前还记得的东西拿出来凉凉,以免发霉了,再则也可以给自己的生活添点佐料。
一、PriorityQueue的数据结构
PriorityQueue类定义里明确指出“based on a priority heap”,堆结构,再简单一点说就是一棵完全二叉树。啥是完全二叉树,还好大学时期学的那点东西还没就饭吃,即除了树的叶子所在的层外,其余层节点都被填满。她的可以使用数组来实现。这里的PriorityQueue只不过是在构造队列时就已经实现的一个堆排序而已。
二、核心操作offer
offer中的核心方法是siftUp,而siftUp的核心方法是siftUpUsingComparator和siftUpComparable,这里我们以siftUpComparable方法为例:
private void siftUpComparable(int k, E x) {
Comparable<? super E> key = (Comparable<? super E>) x;
while (k > 0) {
int parent = (k - 1) >>> 1;(1)
Object e = queue[parent];
if (key.compareTo((E) e) >= 0)
break;
queue[k] = e;
k = parent;
}
queue[k] = key;
}
标号(1)处,这里是堆的一个基本操作:给出节点存储的位置找到其父节点所在的位置。这里用了堆的一个特性,父节点所在的位置=子节点所在位置除以2并向下取整。这个方法的核心就是解决有序堆中新增元素的问题。有序堆中新增元素的核心就是考虑新增元素和其父节点的大小关系问题。
三、核心操作poll
poll中的核心方法是siftDown,而siftDown的核心方法是siftDownUsingComparator和siftDownComparable,我们以siftDownComparable方法为例:
private void siftDownComparable(int k, E x) {
Comparable<? super E> key = (Comparable<? super E>)x;
int half = size >>> 1; // loop while a non-leaf
while (k < half) {
int child = (k << 1) + 1;(1)
Object c = queue[child];
int right = child + 1;(2)
if (right < size &&
((Comparable<? super E>) c).compareTo((E) queue[right]) > 0)
c = queue[child = right];
if (key.compareTo((E) c) <= 0)
break;
queue[k] = c;
k = child;
}
queue[k] = key;
}
这个方法核心解决一个问题,堆的根节点被删除后,如何从堆中选出新的根节点。
(1)处是获取要删除节点的左孩子
(2)处是获取要删除节点的右孩子,后续只要按照堆删除操作要求的考虑将移动节点的子节点同其兄弟节点之间的关系即可