【发布时间】:2016-12-06 09:34:03
【问题描述】:
我一直在阅读 Java 集合 API,优先级队列部分,由两位大师 Josh Bloch 和 Doug Lea 实现。
Java PriorityQueue 是用数组堆实现的。
代码sn-ps在这里,来自PriorityQueue.java,第600行:
/**
* Removes the ith element from queue.
*
* Normally this method leaves the elements at up to i-1,
* inclusive, untouched. Under these circumstances, it returns
* null. Occasionally, in order to maintain the heap invariant,
* it must swap a later element of the list with one earlier than
* i. Under these circumstances, this method returns the element
* that was previously at the end of the list and is now at some
* position before i. This fact is used by iterator.remove so as to
* avoid missing traversing elements.
*/
private E removeAt(int i) {
// assert i >= 0 && i < size;
modCount++;
int s = --size;
if (s == i) // removed last element
queue[i] = null;
else {
E moved = (E) queue[s];
queue[s] = null;
siftDown(i, moved);
//the code I am asking is below:
if (queue[i] == moved) {
siftUp(i, moved);
if (queue[i] != moved)
return moved;
}
}
return null;
}
我想知道的是,曾经位于堆底部的移动元素应该是来自i 的子树中的一个大元素。 siftDown的方法是合理的,在一个siftDown之后,最小的子树会被提升到i的位置。
问题是,如果i没有改变,即siftDown之后移动的仍然存在,在我看来子树已经被堆化了,它不需要再次成为siftUp .
为什么乔希又把他们举到了顶端?
希望看过代码的朋友帮忙!
【问题讨论】:
标签: java heap priority-queue