算法原理
堆排序(Heap Sort)是指利用堆这种数据结构所设计的一种排序算法。堆积是一个近视完全二叉树的结构,并同时满足堆积的性质:即子节点的键值或索引总是小于(或者大于)它的父节点。堆排序可以说是一种利用堆的概念来排序的选择排序。分为两种方法:
- 大顶堆:每个节点的值都大于或等于其子节点的值,在堆排序算法中用于升序排序。
- 小顶堆:每个节点的值都小于或等于其子节点的值,在堆排序算法中用于降序排序。
堆排序的平均时间复杂度为O(nlogn)。
算法描述
- 将初始待排序关键字序列(R1,R2,…,Rn)构建成大顶堆,以此为初始的无序区。
- 将堆顶元素R[1]与最后一个元素R[n]交换,此时得到新的无序区(R1,R2,…,Rn-1)和新的有序区(Rn),且满足R[1,2,…,n-1]<=R[n]。
- 由于交换后新的堆顶R[1]可能违反堆的性质,因此需要堆当前无序区(R1,R2,…,Rn-1)调整为新堆,然后再次将R[1]与无序区最后一个元素交换,得到新的无序区(R1,R2,…,Rn-2)和新的有序区(Rn-1,Rn)。不断重复此过程直到有序区的元素个数为n-1,则整个排序过程完成。
动图展示
注:动图来源于菜鸟教程
算法实现
/**
* 堆排序
*/
public class HeapSort {
public static void main(String[] args) {
int[] arr = {3,44,38,5,47,15,36,26,27,2,46,4,19,50,48};
arr = heapSort(arr);
printArray(arr);
}
public static void printArray(int[] arr){
for(int a : arr)
System.out.print(a+",");
System.out.println();
}
public static int[] heapSort(int[] arr){
int len = arr.length;
buildMaxHeap(arr,len);
for(int i=arr.length-1;i>0;i--){
swap(arr,0,i);
len--;
heapify(arr,0,len);
}
return arr;
}
public static void swap(int[] arr, int i, int j){
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
public static void buildMaxHeap(int[] arr,int len){ // 建立大顶堆
for(int i = (int) Math.floor(len/2); i>=0; i--){
heapify(arr,i,len);
}
}
public static void heapify(int[] arr, int index, int len){ //堆调整
int left=index*2+1;
int right=index*2+2;
int largest=index;
if(left < len && arr[left] > arr[largest]){
largest = left;
}
if(right < len && arr[right] > arr[largest]){
largest = right;
}
if(largest != index){
swap(arr,index,largest);
heapify(arr,largest,len);
}
}
}