1.知识储备:
2.堆的API设计:
上浮算法图解:
下沉算法图解:
3代码实现:
package heap;
public class Heap<T extends Comparable<T>>{
//存储堆中的元素,用数组实现
private T[] items;
//记录堆中元素的个数
private int N;
public Heap(int capacity) {
// TODO Auto-generated constructor stub
this.items=(T[]) new Comparable[capacity+1];
this.N=0;
}
//判断堆中索引i处的元素是否小于j处的元素
private boolean less(int i,int j){
return items[i].compareTo(items[j])<0;
}
//交换堆中i处索引和j处索引的值
private void exch(int i,int j){
T item =items[i];
items[i]=items[j];
items[j]=item;
}
//往堆中插入一个元素
public void insert(T t){
items[++N]=t;
swim(N);
}
//使用上浮算法,使得索引k处的元素再堆中处于一个正确的位置
private void swim(int k){
//通过循环不断地比较当前节点的值与其父节点的值,如果发现父节点的值比当前节点的值小,则交换位置
//while循环的结束条件为k>1,因为ke最小可以上浮到根节点的左子树位置,当k<=1就不用比较了
while(k>1){
//比较当前节点和其父节点
//如果其父节点比当前节点的值要小
if(less(k/2,k)){
//交换他们两的位置
exch(k/2,k);
//变换k的值,以便继续比较
k=k/2;
}
//这里要注意一个bug,k/2的值不小于k的值,那么由于k的值无法改变,程序就会陷入死循环,所以这里要设置一下,不满足条件则退出循环
else{
break;
}
}
}
//使用下沉算法,使得索引k处的元素再堆中处于一个正确的位置
private void sink(int k){
//通过循环不断对比,当前k节点和其左子节点2k以及其右子节点2k+1元素中的较大值进行比较,如果当前节点小,则交换位置
//while循环的条件为2*k<=N,这样才能保证当前节点有左子节点
while(2*k<=N){
//获取当前节点的左右子节点中的较大值
//记录较大值所在的索引
int max;
//如果当前节点存再右子节点
if(2*k+1<=N){
//比较左右子节点的值
//如果左子节点小于右子节点
if(less(2*k,2*k+1)){
//较大值为右子节点索引
max=2*k+1;
}else{
max=2*k;
}
}
//如果不存在右子节点
else{
//较大值直接等于左子节点
max=2*k;
}
//比较当前节点和较大值的节点的值
//如果当前节点的值不小于它子节点的值,直接结束循环即可
if(!less(k,max)){
break;
}
//交换索引k处和索引max处的值
else{
exch(k,max);
//变换k的值,继续比较
k=max;
}
}
}
//删除堆中的最大元素,并返回这个元素
public T delMax(){
T max=items[1];
//交换索引1处元素和最大索引处元素的值,让完全二叉树最右侧的元素变为临时的根节点
exch(1,N);
//最大索引处的元素删除掉
items[N]=null;
//元素个数-1
N-=1;
//通过下沉调整堆,让堆重新有序
sink(1);
return max;
}
//提供遍历方法
public void traversal(){
for(int i=1;i<items.length;i++){
System.out.print(items[i]+"->");
}
System.out.println();
}
}
4.测试案例:
package heap;
public class heapTest1 {
public static void main(String[] args) {
//创建堆对象
Heap<String> heap1 =new Heap<String>(10);
//往堆中插入字符串数据
heap1.insert("D");
heap1.insert("C");
heap1.insert("A");
heap1.insert("F");
heap1.insert("B");
heap1.insert("G");
heap1.insert("E");
heap1.insert("J");
heap1.insert("H");
heap1.insert("I");
//通过循环从堆中删除元素,如果程序写的没有问题,那么每次删除的元素索引为一的元素,而且是元素中值最大的
//遍历
heap1.traversal();
/*
String result=null;
while((result=heap1.delMax())!=null){
System.out.print(result+"->");
}
System.out.println("\n-----------------------------------------------------------------------");
*/
}
}
6.测试结果