堆排序:學習記錄

堆排序

核心要點:

  • 通過下沉的方式,自底向上進行建堆 ,可以保證當檢測到有父節點的堆有序時,其所有子堆都是滿足堆的成立條件。即父節點大於任意兩個子節點
  • 下沉排序的過程,實質上是在刪除最大元素後,堆的自我調整過程。調整的過程中,堆逐漸構成一個有序序列
  • 父節點的座標是左子節點的一半,所以開頭要減一。
  • 由於使用了一個完全二叉樹,因此索引爲0的位置不能有數
public static void heapSort(int[] arr) {
    int N = arr.length - 1;
    // 建堆的模式是自下而上進行的,完全二叉樹的性質,數組從1開始記錄
    for (int i = N / 2; i >= 1; i--) {
        // 下沉建堆。保證父節點比兩個子節點大
        sink(arr, i, N);
    }
    while (N > 1) {
        // 將最大的值交換到最後面(刪除最大元素),並且數組長度減一。這樣下去可以得到最終有序的數組
        swap(arr, 1, N--);
        // 原堆被打破,從子節點選擇一個最大的替換堆頂。對交換後的堆進行下沉再排序
        sink(arr, 1, N);
    }
}

private static void sink(int[] arr, int a, int N) {
    // 需要從上至下進行遍歷
    while (2 * a <= N) {
        // 子節點座標
        int j = a * 2;
        // 右子節點比左子節點大,選擇右子節點, 並且座標要保證不超過N
        if (j < N && arr[j + 1] > arr[j]) j++;
        // 如果父堆比子堆大,則不需要下沉。因爲默認是從下自上建堆的
        if (arr[a] > arr[j]) break;
        // arr[a] < arr[j] 交換a和j的位置,因爲j的序號較大,需要將較大值放到後面
        swap(arr, a, j);
        // 繼續遍歷子節點
        a = j;
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章