1. 程式人生 > >學習筆記:堆排序

學習筆記:堆排序

inf 參與 一次 heapsort 過程 com 父節點 根節點 數組

一、定義

①堆通常是可被視為完全二叉樹的數組。

②堆中任意節點的數值總是大於或等於其左右子節點,為大根堆。

③堆中任意節點的數值總是小於或等於其左右子節點,為小根堆。

二、存儲

對於任意節點T[i]

①若其父節點存在,為T[(i - 1) / 2]

②若其左兄弟節點存在,為T[i - 1]

③若其右兄弟節點存在,為T[i + 1]

④若其左子節點存在,為T[i * 2 + 1]

⑤若其右子節點存在,為T[i * 2 + 2]

數組表示

技術分享圖片

二叉樹表示

技術分享圖片

三、調整(大根堆)

①若數值大於選擇節點的左右子節點存在,則交換選擇節點與左右子節點中數值較大者。

②若數值大於選擇節點的左右子節點不存在,則該選擇節點的調整結束。

具體過程如下:

假設選擇根節點進行調整。

技術分享圖片

將選擇節點與數值較大的右子節點進行交換。至此調整結束,不存在大於選擇節點的左右子節點。

技術分享圖片

四、排序

①構建大根堆。從最後一個非葉節點開始,從下到上、從右到左選擇每個非葉節點進行一次調整。

②調整堆結構。從最後一個節點開始,從下到上、從左到右將每個節點與根節點進行交換後,選擇根節點進行一次調整。已經與根節點交換過的位置不參與調整。

具體過程如下:

選擇7進行調整。

技術分享圖片

選擇5進行調整。

技術分享圖片

選擇6進行調整。

技術分享圖片

交換1和7,選擇根節點1進行調整。

雖然7大於2,但7所處的位置已與根節點進行過交換,所以不參與調整。

技術分享圖片

交換1和6,選擇根節點1進行調整。

技術分享圖片

交換3和5,選擇根節點3進行調整。

雖然5大於3,但5所處的位置已與根節點進行過交換,所以不參與調整。

技術分享圖片

交換1和4,選擇根節點1進行調整。

技術分享圖片

交換2和3,選擇根節點2進行調整。

技術分享圖片

交換1和2,選擇根節點1進行調整。

技術分享圖片

排序結束,二叉樹對應的數組有序。

五、實現

public class HeapSort {
    private static void swap(int[] array, int i, int j) {
        int temp = array[i];
        array[i] = array[j];
        array[j] = temp;
    }

    
private static void adjust(int[] array, int i, int length) { int temp = array[i]; for (int j = i * 2 + 1; j < length; j = j * 2 + 1) { if (j + 1 < length && array[j] < array[j + 1]) j = j + 1; if (array[j] > temp) { array[i] = array[j]; i = j; } else break; } array[i] = temp; } public static void sort(int[] array) { for (int i = (array.length - 1) / 2; i >= 0; i--) adjust(array, i, array.length); for (int j = array.length - 1; j > 0; j--) { swap(array, 0, j); adjust(array, 0, j); } } }

學習筆記:堆排序