基本思想
1)将初始待排序关键字序列(R1,R2....Rn)构建成大顶堆,此堆为初始的无序区;
2)将堆顶元素R[1]与最后一个元素R[n]交换,此时得到新的无序区(R1,R2,......Rn-1)和新的有序区(Rn),且满足R[1,2...n-1]<=R[n];
3)由于交换后新的堆顶R[1]可能违反堆的性质,因此需要对当前无序区(R1,R2,......Rn-1)调整为新堆,然后再次将R[1]与无序区最后一个元素交换,得到新的无序区(R1,R2....Rn-2)和新的有序区(Rn-1,Rn)。不断重复此过程直到有序区的元素个数为n-1,则整个排序过程完成。
操作过程
1)初始化堆:将R[1..n]构造为堆;
2)将当前无序区的堆顶元素R[1]同该区间的最后一个记录交换,然后将新的无序区调整为新的堆。
代码实现
package com.csdhsm.sort; /** * @Title: HeapSort.java * @Package: com.csdhsm.sort * @Description 堆排序 * @author Han * @date 2016-4-3 下午3:55:18 * @version V1.0 */ public class HeapSort { /** * @Description 调整堆 * @author Han * @param arr * @param i * @param size */ private void heapAdjust(int[] arr,int i,int size){ int lchild = i*2+1;//i节点的左子节点 int rchild = i*2+2;//i节点的右子节点 /** * 右子节点大于左子节点 */ if(rchild < size && arr[rchild] > arr[lchild]){ swap(arr,lchild,rchild); } /** * 左子节点大于根节点 */ if(lchild < size && arr[lchild] > arr[i]){ swap(arr,lchild,i); } } /** * @Description 建立堆 * @author Han */ private void buildHeap(int[] arr,int size){ int i = 0; //依次调整各个堆 for(i = size/2;i>=1;i--){ heapAdjust(arr,i-1,size); } } public void sort(int[] arr,int len){ buildHeap(arr,len); for(int i = len-1 ; i>=1;i--){ //将有序堆中的第一个元素和最后一个元素交换,取出最后一个元素 swap(arr,0,i); //将无序堆重新构造为有许多 buildHeap(arr,i); } } /** * @Description 自定义交换方法 * @author Han * @param arr * @param firstIndex * @param secondIndex */ private void swap(int arr[],int firstIndex,int secondIndex){ int temp = arr[firstIndex]; arr[firstIndex] = arr[secondIndex]; arr[secondIndex] = temp; } }
效率分析
不稳定
空间复杂度:O(1)
时间复杂度:O(nlog2n)
最坏情况:O(nlog2n)
最好情况:O(nlog2n)