堆排序是指利用堆這種數據結構所設計的一種排序算法。堆的特點是子結點總是小於(或者大於)它的父節點,根節點最大的堆叫做最大堆,根節點最小的堆叫做最小堆。根據升序或降序的排序需求選擇使用最大堆還是最小堆,本文以升序排列爲例,所以選用最大堆。
堆排序的基本思想是:將原始序列先調整爲一個最大堆,這樣根頂元素就是整個序列的最大值;將其與末尾元素交換,這樣該序列最大元素就歸位了;將剩下的N-1個元素再調整爲最大堆,再次交換根頂元素和本次末尾元素,這樣次大值也歸位了;反覆循環,直到整個序列都有序。
java示例:
public class HeapSort {
public static void main(String[] args) {
int[] arr = {1,3,2,6,4,66,32,65,34,67,45,77,78,36,56};
System.out.println("排序前:");
System.out.println(Arrays.toString(arr));
sort(arr);
System.out.println("排序後:");
System.out.println(Arrays.toString(arr));
}
public static void sort(int[] arr) {
//構建最大堆
for (int i = arr.length/2 - 1; i >= 0; i--) {
handleHeap(arr, i, arr.length);//從最末尾的非葉子節點,自右至左,自下而上調整
}
for (int j = arr.length - 1; j > 0; j--) {
swap(arr, 0, j);//交換根頂元素和末尾元素
handleHeap(arr, 0, j);//重新調整成最大堆
}
}
//調整最大堆(建立在最大堆已構建的基礎上)
public static void handleHeap(int[] arr, int i, int length) {
int temp = arr[i];//先取出當前元素i
for (int k = i * 2 + 1; k < length; k = k * 2 + 1) {//從i結點的左子結點開始,也就是2i+1處開始
if (k + 1 < length && arr[k] < arr[k + 1]) {//如果左子結點小於右子結點,k指向右子結點
k++;
}
if (arr[k] > temp) {//如果子節點大於父節點,將子節點值賦給父節點(不用進行交換)
arr[i] = arr[k];
i = k;
} else {
break;
}
}
arr[i] = temp;//將temp值放到最終的位置
}
//交換數組中兩個元素
private static void swap(int[] arr, int i, int j) {
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}
執行結果:
排序前:
[1, 3, 2, 6, 4, 66, 32, 65, 34, 67, 45, 77, 78, 36, 56]
排序後:
[1, 2, 3, 4, 6, 32, 34, 36, 45, 56, 65, 66, 67, 77, 78]
Process finished with exit code 0