堆排序
思想
将初始待排序关键字序列(R0,R2....Rn-1)构建成大顶堆。
将堆顶元素R[0]与最后一个元素R[n-1]交换,此时得到新的无序区(R0,R1,R2,......Rn-2)和新的有序区(R[n-1]),且满足R[0,2...n-2]<=R[n-1];
由于交换后新的堆顶R[0]可能违反堆的性质,因此需要对当前无序区(R0,R1,R2,......Rn-2)调整为新堆,然后再次将R[0]与无序区最后一个元素交换,得到新的无序区(R0,R2....Rn-3)和新的有序区(R[n-1],R[n-2])。不断重复此过程直到有序区的元素个数为n-1,则整个排序过程完成。
示例
n=11,i=n/2-1 to 0 ,调用heapify(array,i,n-1)把堆调整为大顶堆
依次循还……
至此大顶堆就建好了!
然后,array【0】与array【10】交换
此时100已经在正确的位置上,此时再维护array【0】至array【9】的堆
然后array【0】与array【9】交换,循还下去……
关键代码
//构建大顶堆
public static void buildHeap(int[] array,int n){
//非叶子结点的操作
for(int i=n/2-1;i>=0;i--){
heapify(array,i,n-1);
}
}
//调整大顶堆
public static void heapify(int[] array,int index,int max){
int left=2*index+1;
int right=2*index+2;
int largest = index;
if(left<=max&&array[largest]<array[left]){
largest=left;
}
if(right<=max&&array[largest]<array[right]){
largest=right;
}
//如果任一子节点比父节点大则交换,之后维护下级节点
if(largest!=index){
swap(array,index,largest);
heapify(array,largest,max);
}
}
//堆排序
public static void HeapSort(int[] array,int n){
buildHeap(array,n);
//建堆之后依次交换并调整维护为新的大顶堆
for(int i=n-1;i>0;i--){
swap(array,0,i);
heapify(array,0,i-1);
}
}
public static void swap(int[] array,int i,int j){
int temp;
temp=array[i];
array[i]=array[j];
array[j]=temp;
}
复杂度
“空间复杂度”指占内存大小,堆排序每次只对一个元素操作,是就地排序,所用辅助空间O(1),空间复杂度是O(1)。构建堆的时间复杂度是O(nlogN)。