1. 程式人生 > >基本演算法_堆排序_Java實現

基本演算法_堆排序_Java實現

1.堆排序

  堆排序就是將序列調整為指定的堆,然後調整首尾元素的位置,取出末尾元素,反覆進行,直到將所有元素取出,形成一個有序的序列。假設存在n個元素的序列{R0,R1,Rn},其中父節點值不大於子節點值的堆稱為小根堆(RiR2i+1RiR2i+2),父節點的值不小於子節點的堆稱為大根堆(RiR2i+1RiR2i+2)

堆排序
  存在一個序列【7】【5】【9】【6】【8】,按照從小到大的順序進行排序。
  ①將無序序列構造成一個堆。
  ②取出子節點中6和8較大的值,與父節點5進行比較,比父節點5大,則交換位置。
  ③取出子節點中8和9較大的值,與根節點7進行比較,比跟節點7大,則交換位置,此時序列已調整為大根堆。
  ④將節點9和5調換位置,同時取出節點9,然後按照相同的方式將序列轉換為大根堆,取出序列中最大的數,重複操作直到序列中所有數取出完畢,生成一個新的有序序列。

2.示例程式碼

  存在一個序列N由小到大進行排序,將序列轉換為大根堆,交換首尾元素的位置,再將子序列N-1轉換為大根堆,交換收尾元素位置,反覆進行,當子序列剩餘一個元素時,此時的序列為一個有序序列。

public class HeapSort {

    public static void main(String[] args) {
        int[] array = { 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 };
        HeapSort.sort(array);
        System.out.println("排序後陣列:" + Arrays.toString(array));
    }

    public static void sort(int[] a) {
        // 迴圈建立初始堆,若父節點索引為i,那麼左節點的索引為i*2+1,即左節點為a.length時,其父節點應當小於a.length/2
        for (int i = a.length / 2; i >= 0; i--) {// 遍歷存在子節點的父節點
            adjustHeap(a, i, a.length - 1);
        }

        // 進行n-1次迴圈完成排序
        for (int i = a.length - 1; i > 0; i--) {
            // 最後一個元素和第一個元素進行交換
            int temp = a[i];
            a[i] = a[0];
            a[0] = temp;

            adjustHeap(a, 0, i);
        }
    }

    // 將陣列轉換為大根堆,大根堆的根節點為陣列中的最大值
    public static void adjustHeap(int[] a, int parent, int length) {
        int temp = a[parent]; // 父節點的值
        int child = 2 * parent + 1; // 左子節點的索引

        while (child < length) {// 判斷左節點是否為最大索引
            // 如果有右孩子結點,並且右孩子結點的值大於左孩子結點,則選取右孩子結點
            if (child + 1 < length && a[child] < a[child + 1]) {
                child ++;// 將左子節點轉換為右子節點
            }
            // 當父節點的值直接大於子節點的值時,直接退出
            if (temp > a[child])
                break;
            // 將子節點的值賦值給父節點
            a[parent] = a[child];
            // 選取子節點的左子節點繼續向下篩選
            parent = child;
            child = 2 * parent + 1;
        }
        // 若發生交換,此時parent代表子節點索引,沒有發生交換,此時parent仍舊代表父節點索引
        a[parent] = temp;
    }

}

3.演算法分析

時間複雜度:堆排序的時間複雜度為O(nlog2n)
演算法穩定性:排序前後相同元素間的相對位置可能會發生改變,堆排序是一種不穩定的排序演算法。