优先队列由一个基于堆的完全二叉树表示,存储与a[1~N]中,a[0]没有使用。
插入元素:将新元素加到数组末尾,增加堆的大小,并让元素上浮到合适的位置。
删除最大元素:我们将最后一个元素与第一个元素(最大元素)交换,并将最后一个(最大元素的)位置设为空。然后使用sink方法,将交换到第一位的元素放置到正确位置。
注:根据可需求添加reSize()方法,扩展数组的大小。
/*
通过创建一个temp的数组,大小为数组的两倍。然后通过for循环将所有元素复制。最后,原数组 = temp;即可。
*/
具体代码如下:
package algorithm;
public class MaxPQ<Key extends Comparable<Key>> {
private int N = 0;//基于堆的完全二叉树
private Key[] pq;//存储于pq[1...N]中,pq[0]没有使用
public MaxPQ(int maxN) {
pq = (Key[])new Comparable[maxN+1];
}
//将元素插在最后,并使用swim方法将其排序
public void Insert(Key v) {
pq[++N] = v;
swim(N);
}
public boolean isEmpty() {
return N==0;
}
public int size() {
return N;
}
public Key delMax() {
Key max =pq[1];//从根结点得到最大元素
exch(1,N--); //将其和最后一个结点交换
pq[N+1] =null; //将最后一个结点设为null(删除),防止对象的游离
sink(1); //恢复堆的有序性
return max;
}
//上升
private void swim(int k) {
/*
* 由于k为int类型,故无论是哪个子节点,除以2都会得到其父节点
* 如第二层:k=2及k=3,2/2=1,3/2=1(强制转化为int类型)
*/
while(k>1&&less(k/2,k)){
exch(k/2,k);
k = k/2;
}
}
//下沉
private void sink(int k) {
while(2*k<=N) {
int j = 2*k;
if(j<N&&less(j,j+1)) j++;//比较k下边的两个子节点,取大的那个,j>j+1时,取j,否则,j++
if(!less(k,j)) break;//如果k小于相对较大的那个子节点,则说明不用再移动,退出循环
exch(k,j);//如果k大于相对较大的子节点,则交换位置
k = j;
}
}
private boolean less(int i,int j) {
return pq[i].compareTo(pq[j])<0;
}
private void exch(int i, int j) {
Key temp =pq[i];
pq[i] = pq[j];
pq[j] = temp;
}
public static void main(String[] args) {
int maxN =2;
MaxPQ<Integer> pq = new MaxPQ<Integer>(maxN);
}
}