如果堆的大小是提前知道的,那么可以将堆存储在一个ArrayList或一个数组里。如下图使用数组存储堆,对于位置i处的结点,它的左孩子在位置2i+1处,它的右孩子在位置2i+2处,而它的父亲在位置(i - 1)/2处。
如下是一些堆具有的常见操作:
添加一个新结点:
为了给堆添加一个新结点,首先将它添加到堆的末尾,然后和它的父节点比较,如果大,就上移,直到不必父节点大。
删除根节点:
经常需要从堆中删除最大的元素,也就是这个堆中的根节点。删除根节点之后就必须重建这个树以保持堆的特性,重建过程如下:
将最后一个节点放到根节点当做当前节点;
然后和左右子节点比较,如果当前节点是这三个节点中最大的,那么这棵树建立成功;如果不是,需要和两个子节点中最大的节点交换位置,然后以当前位置作为当前节点,继续和子节点比较,直到当前节点是最大的,或者当前节点已经成为叶子节点。
Heap.java代码如下:
package test;
public class Heap<E extends Comparable> {
private java.util.ArrayList<E> list = new java.util.ArrayList<E>();
public Heap(){}
public Heap(E[] objects){
for(int i = 0; i < objects.length; i++)
add(objects[i]);
}
public void add(E newObject){
list.add(newObject);
int currentIndex = list.size() - 1;
while(currentIndex > 0){
int parentIndex = (currentIndex - 1)/2;
if(list.get(currentIndex).compareTo(list.get(parentIndex)) > 0){
E temp = list.get(currentIndex);
list.set(currentIndex, list.get(parentIndex));
list.set(parentIndex, temp);
}
else
break;
currentIndex = parentIndex;
}
}
public E remove(){
if(list.size() == 0) return null;
E removedObject = list.get(0);
list.set(0, list.get(list.size() - 1));
list.remove(list.size() - 1);
int currentIndex = 0;
while(currentIndex < list.size()){
int leftChildIndex = 2 * currentIndex + 1;
int rightChildIndex = 2 * currentIndex + 2;
if(leftChildIndex >= list.size()) //这说明当前节点已经是叶子了,这时树已经是堆
break;
int maxIndex = leftChildIndex;
if(rightChildIndex < list.size()){ //这一段是为了找到左右子节点中最大的节点
if(list.get(rightChildIndex).compareTo(list.get(maxIndex))> 0){
maxIndex = rightChildIndex;
}
}
if(list.get(currentIndex).compareTo(list.get(maxIndex)) < 0){
E temp = list.get(currentIndex);
list.set(currentIndex, list.get(maxIndex));
list.set(maxIndex, temp);
currentIndex = maxIndex;
}
else
break; //这时树已经是堆
}
return removedObject;
}
}
HeapSort.java代码如下:
package test;
public class HeapSort {
public static <E extends Comparable> void heapSort(E[] list){
Heap <E> heap = new Heap<E>();
for(int i = 0; i < list.length; i++)
heap.add(list[i]);
for(int i = list.length - 1; i >= 0; i--)
list[i] = heap.remove();
}
public static void main(String []args){
Integer [] list = {1,2,3,4,5,6};
// int [] list = {5, 2, 9, 3, 8, 4, 5, 5, 0, 1, 6, 7};
for(int i = 0; i < list.length; i++)
System.out.print(list[i] + " ");
System.out.print("\n");
heapSort(list);
for(int i = 0; i < list.length; i++)
System.out.print(list[i] + " ");
}
}