1. 程式人生 > 其它 >演算法-堆排序

演算法-堆排序

堆排序

  • 先讓整個陣列都變成大根堆結構,建立堆的過程
    • 從上到下的方法,時間複雜度為O(logN*N)
    • 從下到上的方法,時間複雜度為O(N)
  • 把堆的最大值和堆末尾的值進行交換,然後減少堆的大小之後,再去調整堆,一直周而復始,時間複雜度為O(N)
  • 堆的大小減成0之後,排序完成

圖示

程式碼

其實你會將資料調整為 小根堆或者大根堆,你就會堆排序了

從上到下構建堆

    /**
     * 
     * 從上之下
     * @param heap
     * @param index
     */
    public void heapInsert(int[] heap, int index) {
        
        // 父節點(index - 1) / 2小於當前節點
        while (heap[(index - 1) / 2] < heap[index]) {
            // 交換
            swap(heap,(index - 1) / 2,index);
            index = (index - 1) / 2;
        }
    }

從下到上構建堆

private void heapfiy(int[] arr, int index, int heapSize) {
        // 獲取當前index 的左孩子
        int left = index * 2 + 1;

        // 左孩子節點小於堆大小
        while (left < heapSize) {

            // 孩子節點的最大 值的位置值
            int lagest = left + 1 < heapSize && arr[left + 1] > arr[left] ? left + 1 : left;

            // 判斷index 和孩子節點的值大小
            lagest = arr[index] > arr[lagest] ? index : lagest;

            // 如果當前節點就是最大的不需要繼續下沉,跳出
            if (lagest == index) {
                break;
            }
            // 交換
            swap(arr, index, lagest);

            index = lagest;

            // 獲取最大的節點的左孩子節點
            left = index * 2 + 1;
        }

    }

整個堆排序程式碼



public class HeapSort {

    private void heapfiy(int[] arr, int index, int heapSize) {
        // 獲取當前index 的左孩子
        int left = index * 2 + 1;

        // 左孩子節點小於堆大小
        while (left < heapSize) {

            // 孩子節點的最大 值的位置值
            int lagest = left + 1 < heapSize && arr[left + 1] > arr[left] ? left + 1 : left;

            // 判斷index 和孩子節點的值大小
            lagest = arr[index] > arr[lagest] ? index : lagest;

            // 如果當前節點就是最大的不需要繼續下沉,跳出
            if (lagest == index) {
                break;
            }
            // 交換
            swap(arr, index, lagest);

            index = lagest;

            // 獲取最大的節點的左孩子節點
            left = index * 2 + 1;
        }

    }


    /**
     * 陣列兩個位置交換
     * @param arr
     * @param i
     * @param j
     */
    private void swap(int[] arr, int i, int j) {
        int tmp = arr[i];
        arr[i] = arr[j];
        arr[j] = tmp;
    }

    @Test
    public void testHeapSort() {
        int[] arr = {1, 20,18, 6, 9, 2, 10, 11, 7};

        // 構建最大根堆
        for (int i = 0; i < arr.length; i++) {
            heapfiy(arr, arr.length - 1 - i, arr.length);
        }

        System.out.println("----------------------");
        for (int i : arr) {
            System.out.print (i+" ");
        }
        System.out.println();
        System.out.println("----------------------");

        /*
         * 最大跟交換
         * heapSize --
         * heapFiy呼叫
         */
        int len = arr.length;
        for (int i = 0; i < arr.length - 1; i++) {
            swap(arr, 0, len - 1);
            heapfiy(arr, 0, --len);
        }
        
        System.out.println("++++++++++++++++++");
        for (int i : arr) {
            System.out.print (i+" ");
        }
        System.out.println();
        System.out.println("++++++++++++++++++");
    }
}