堆排序使用的是二叉堆,它是一棵完全二叉树。
堆(Heap)是一棵有以下属性的二叉树:
1.它是一棵完全二叉树
2.每个节点大于或等于任意一个孩子
/*实现Heap类*/
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(maxIndex).compareTo(list.get(rightChildIndex))<0)
maxIndex=rightChildIndex;
}
if(list.get(currentIndex).compareTo(list.get(maxIndex))<0){//父结点小于子结点,交换
E temp=list.get(maxIndex);
list.set(maxIndex, list.get(currentIndex));
list.set(currentIndex, temp);
currentIndex=maxIndex;
}
else
break;
}
return removedObject;
}
public int getSize(){//返回堆的大小
return list.size();
}
}
/*堆排序*/
import java.util.*;
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={2,3,2,5,6,1,-2,3,14,12};
heapSort(list);
for(int i=0;i<list.length;i++)
System.out.print(list[i]+" ");
}
}
由于add方法会追踪从叶结点到根结点的路径,因此,添加一个新元素最多需要h步,即建立包含n个元素的初始堆,需要O(nlogn)时间。remove追踪从根结点到叶结点,需要时间同为O(nlogn)。时间效率与归并排序相同,空间效率高于归并排序。