一、数据结构
transient Object[] queue; // non-private to simplify nested class access
1、PriorityQueue使用二叉堆(基于数组,queue[n]的子节点是queue[2*n+1]、queue[2*n+2])实现。
2、扩容机制:
private static final int DEFAULT_INITIAL_CAPACITY = 11;
private void grow(int minCapacity) {
int oldCapacity = queue.length;
// Double size if small; else grow by 50%
int newCapacity = oldCapacity + ((oldCapacity < 64) ?
(oldCapacity + 2) :
(oldCapacity >> 1));
// overflow-conscious code
if (newCapacity - MAX_ARRAY_SIZE > 0)
newCapacity = hugeCapacity(minCapacity);
queue = Arrays.copyOf(queue, newCapacity);
}
默认初始容量11,容量<64时双倍扩容,否则扩容50%
二、主要方法
1、siftUp:沿着从queue[k]到根节点的唯一一条路径,把x移到适合它的位置上。(关键点:int parent = (k - 1) >>> 1)
private void siftUpComparable(int k, E x) {
Comparable<? super E> key = (Comparable<? super E>) x;
while (k > 0) {
int parent = (k - 1) >>> 1;
Object e = queue[parent];
if (key.compareTo((E) e) >= 0)
break;
queue[k] = e;
k = parent;
}
queue[k] = key;
}
2、siftDown:沿着从queue[k]到叶子节点的路径,把x“渗”到二叉树中适合它的位置上。(需要与左右两个子节点分别比较)
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; // assume left child is least
Object c = queue[child];
int right = child + 1;
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;
}
3、removeAt:把末尾元素放入删除位置后,在执行siftDown或者siftUp操作
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);
if (queue[i] == moved) {
siftUp(i, moved);
if (queue[i] != moved)
return moved;
}
}
return null;
}
4、heapify:堆化,循环所有非叶子节点执行siftDown操作
private void heapify() {
for (int i = (size >>> 1) - 1; i >= 0; i--)
siftDown(i, (E) queue[i]);
}
5、add&offer:插入尾部,然后通过siftUp操作移动到合适的位置上
public boolean offer(E e) {
if (e == null)
throw new NullPointerException();
modCount++;
int i = size;
if (i >= queue.length)
grow(i + 1);
size = i + 1;
if (i == 0)
queue[0] = e;
else
siftUp(i, e);
return true;
}
6、peek:返回堆顶元素
public E peek() {
return (size == 0) ? null : (E) queue[0];
}
7、poll:弹出堆顶元素,把尾部元素先放入堆顶,再执行shitDown操作移动到合适的位置上
public E poll() {
if (size == 0)
return null;
int s = --size;
modCount++;
E result = (E) queue[0];
E x = (E) queue[s];
queue[s] = null;
if (s != 0)
siftDown(0, x);
return result;
}