package com.prince.algorithm;
/**
* 利用二叉堆实现优先队列
* @author Prince
*
* @param <Key>
*/
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]; //从根结点得到最大的元素
exch(1,N--); //将其和最后一个结点交换
pq[N++] = null;
sink(1); //恢复堆的有序
return max;
}
/**
* 由下至上的堆有序化
* 堆的有序状态因为某个结点变得比它的父结点更大被打破,交换其和其
* 父结点来修复。交换后,该结点比它的两个子节点都大(一个是其曾经父结点,
* 另一个是其父结点的子节点)重复此过程至稳定状态
* @param k
*/
private void swim(int k) {
while(k>1&&less(k/2,k)) {
exch(k/2,k);
k = k/2;
}
}
/**
* 由上至下的堆有序化
* 某个结点比它的两个子节点或其中之一更小了,通过将它和它的两个子
* 结点中的较大者交换来使堆稳定
* @param k
*/
private void sink(int k) {
while(2*k<=N) {
int j =2*k;
if(j<N&& less(j,j+1)) j++; //是否有右子树
if(!less(k,j)) break;
exch(k,j);
k=j;
}
}
private boolean less(int i, int j) {
return pq[i].compareTo(pq[j])<0;
}
private void exch(int i, int j) {
Key t = pq[i];
pq[i] = pq[j];
pq[j] = t;
}
}