堆有序的·二叉树,就是每个节点值都是大于等于它的子节点值。
这里用大小为N+1的数组pq来表示一个大小为N的堆,不使用pq[0]。
关于二叉树,有一个特点很重要,就是位置k的父节点是k/2,子节点是2*k和2*k+1。
堆的有序化,包括两种情况:
1.当某个节点的值增大时,采用的是由下至上的堆有序化,比较该节点与它的父节点的值,并根据比较结果交换位置。定义方法swim(上浮)。
2.当某个节点的值减小时,采用的是由上至下的堆有序化,比较该节点与它的较大的那个子节点的值,并根据比较结果交换位置。定义方法sink(下沉)。
实现如下:
package MaxPQ;
public class MaxPQ<Key extends Comparable<Key>>{
private Key[] pq;
private int N= 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 key) {
pq[++N] =key;
swim(N);
}
public Key delMax() {
Key re =pq[1];
exch(1,N);
pq[N] =null;
N--;
sink(1);
return re;
}
private void sink(int k) {//由上至下的堆有序化
while (2*k<=N) {
int j =2*k;
if (less(j,j+1)) {
j=j+1;
}
if (!less(k,j)) {
break;
}
else {
exch(k,j);
k = j;
}
}
}
private void swim(int k) {//由下至上的堆有序化
while (k>1&&less(k/2,k)) {
exch(k/2,k);
k =k/2;
}
}
private void exch(int i, int j) {//交换第i、j个值
Key key = pq[i];
pq[i] = pq[j];
pq[j] = key;
}
private boolean less(int i, int j) {//判断第i个值是否比第j个值小
return pq[i].compareTo(pq[j])<0;
}
}
测试如下:
package MaxPQ;
public class Test {
public static void main(String[] args) {
MaxPQ<Integer> m =new MaxPQ<Integer>(11);
System.out.println(m.isEmpty());
m.insert(2);
m.insert(6);
m.insert(4);
m.insert(7);
m.insert(0);
m.insert(8);
m.insert(3);
m.insert(5);
System.out.println(m.size());
System.out.println(m.delMax());
System.out.println(m.delMax());
System.out.println(m.size());
System.out.println(m.isEmpty());
}
}
结果如下:
true 8 8 7 6 false |