优先队列
下面这个优先队列是由一个基于堆的完全二叉树实现的,其插入和删除最大元素方法都能在对数时间内完成。二叉堆是一组能够用堆有序的完全二叉树排序的元素,并在数组中按照层级存储(不使用第0个元素)。
二叉树有以下两个重要的特性:
1.一颗大小为N的完全二叉树的高度是lgN向下取整
2.k节点的父节点为k/2,两个子节点分别为2k和2k+1
使用上面两个特性实现了sink和swim方法
public class MaxPQ<Key extends Comparable<Key>>{
private Key[] pq; //基于堆的完全二叉树
private int N = 0; //存储于pq[1...N]中,pq[0]没有使用
public MaxPQ(int maxN){
pq = (Key[]) new Comparable[maxN + 1];
}
public boolean isEmpty(){
return N == 0;
}
public int size(){
return N;
}
public void insert(Key v){
pq[++N] = v;
swim(N);
}
public Key delMax(){
Key max = pq[1];
pq[1] = pq[N--]; //获得最后一个元素
pq[N+1] = null; //设置为空,以便系统收回空间
sink(1);
return max;
}
private void sink(int k) {
// TODO Auto-generated method stub
while(2 * k <= N){ //2*k<=N限制了k节点至少要有一个子节点
int j = 2*k;
if(j<N && less(j,j+1)) //当k有两个子节点的时候才能进行比较,若只有一个子节点则j不变
j++;
if(!less(k,j)) //循环终止条件之一,当k已经到达了正确的位置就不再进行移动
break;
exch(k,j);
k = j;
}
}
private void exch(int i, int j) {
// TODO Auto-generated method stub
Key t = pq[i];
pq[i] = pq[j];
pq[j] = t;
}
private boolean less(int i, int j) {
// TODO Auto-generated method stub
return pq[i].compareTo(pq[j])<0;
}
private void swim(int k) {
// TODO Auto-generated method stub
while(k>1 && less(k/2,k)){
exch(k/2,k);
k = k/2;
}
}
}