原文連接:https://jiang-hao.com/articles/2020/algorithms-algorithms-heap-sort.htmlhtml
堆排序(Heapsort)是指利用堆這種數據結構所設計的一種排序算法。堆積是一個近似徹底二叉樹的結構,並同時知足堆積的性質:即子結點的鍵值或索引老是小於(或者大於)它的父節點。堆排序能夠說是一種利用堆的概念來排序的選擇排序。分爲兩種方法:java
堆排序的平均時間複雜度爲 Ο(nlogn)。算法
一般堆是經過一維數組來實現的。在數組起始位置爲0的情形中:api
在堆的數據結構中,堆中的最大值老是位於根節點(在優先隊列中使用堆的話堆中的最小值位於根節點)。堆中定義如下幾種操做:數組
首先第一步和第二步,建立堆,這裏咱們用最大堆;建立過程當中,保證調整堆的特性。數據結構
從最後一個分支的節點開始從右往左,從下至上進行調整爲最大堆。svg
如今獲得的最大堆的存儲結構以下:測試
初始堆建立完成。ui
接着,最後一步,堆排序,進行(n-1)次循環。this
持續整個過程直至最後一個元素爲止。
這個迭代持續直至最後一個元素即完成堆排序步驟。
public class HeapSort { private int[] arr; public HeapSort(int[] arr) { this.arr = arr; } /** * 堆排序的主要入口方法,共兩步。 */ public void sort() { /* * 第一步:將數組堆化 * beginIndex = 第一個非葉子節點。 * 從第一個非葉子節點開始便可。無需從最後一個葉子節點開始。 * 葉子節點能夠看做已符合堆要求的節點,根節點就是它本身且本身如下值爲最大。 */ int len = arr.length - 1; int beginIndex = (arr.length >> 1)- 1; for (int i = beginIndex; i >= 0; i--) maxHeapify(i, len); /* * 第二步:對堆化數據排序 * 每次都是移出最頂層的根節點A[0],與最尾部節點位置調換,同時遍歷長度 - 1。 * 而後重新整理被換到根節點的末尾元素,使其符合堆的特性。 * 直至未排序的堆長度爲 0。 */ for (int i = len; i > 0; i--) { swap(0, i); maxHeapify(0, i - 1); } } private void swap(int i, int j) { int temp = arr[i]; arr[i] = arr[j]; arr[j] = temp; } /** * 調整索引爲 index 處的數據,使其符合堆的特性。 * * @param index 須要堆化處理的數據的索引 * @param len 未排序的堆(數組)的長度 */ private void maxHeapify(int index, int len) { int li = (index << 1) + 1; // 左子節點索引 int ri = li + 1; // 右子節點索引 int cMax = li; // 子節點值最大索引,默認左子節點。 if (li > len) return; // 左子節點索引超出計算範圍,直接返回。 if (ri <= len && arr[ri] > arr[li]) // 先判斷左右子節點,哪一個較大。 cMax = ri; if (arr[cMax] > arr[index]) { swap(cMax, index); // 若是父節點被子節點調換, maxHeapify(cMax, len); // 則須要繼續判斷換下後的父節點是否符合堆的特性。 } } /** * 測試用例 * * 輸出: * [0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 5, 6, 6, 6, 7, 7, 7, 8, 8, 8, 9, 9, 9] */ public static void main(String[] args) { int[] arr = new int[] {3, 5, 3, 0, 8, 6, 1, 5, 8, 6, 2, 4, 9, 4, 7, 0, 1, 8, 9, 7, 3, 1, 2, 5, 9, 7, 4, 0, 2, 6}; new HeapSort(arr).sort(); System.out.println(Arrays.toString(arr)); } }