圖解堆排序

1、引言2、圖解堆排序(heapsort)3、java代碼實現及時間複雜度分析4、總結html

1、引言

優先隊列能夠用於以O(NlogN)時間排序,正如上一篇的求解topK問題中用到的思想同樣,這種思想就是堆排序(heapsort)。java

2、圖解堆排序(heapsort)

  1. 算法思想:經過將數組元素進行buildHeap進行堆序化(構建大頂堆);再對堆進行N-1次deleteMax操做。這裏有個技巧,若是使用新的數組來存儲,須要O(N)的空間;但每次deleteMax會空出一個位置,並將尾端的節點進行下濾操做,那咱們就能夠將deleteMax的數據放到尾端。
  2. 堆排序過程:

對二叉堆不瞭解的能夠看看圖解優先隊列(堆)算法

3、java代碼實現及時間複雜度分析

咱們從數組下標0開始,不像二叉堆從數組下標1開始。數組

  • 代碼實現
public class Heapsort {
    public static void main(String[] args) {
        Integer[] integers = {711391158};
        System.out.println("原序列:" + Arrays.toString(integers));
        heapsort(integers);
        System.out.println("排序後:" + Arrays.toString(integers));
    }

    public static <T extends Comparable<? super T>> void heapsort(T[] a) {
        if (null == a || a.length == 0) {
            throw new RuntimeException("數組爲null或長度爲0");
        }
        //構建堆
        for (int i = a.length / 2 - 1; i >= 0; i--) {
            percDown(a, i, a.length);
        }
        //deleteMax
        for (int i = a.length - 1; i > 0; i--) {
            swapReferences(a, 0, i);
            percDown(a, 0, i);
        }
    }

    /**
     * 下濾的方法
     *
     * @param a:待排序數組
     * @param i:從哪一個索引開始下濾
     * @param n           :二叉堆的邏輯大小
     * @param <T>
     */

    private static <T extends Comparable<? super T>> void percDown(T[] a, int i, int n) {
        int child;
        T tmp;
        for (tmp = a[i]; leftChild(i) < n; i = child) {
            child = leftChild(i);
            if (child != n - 1 && a[child].compareTo(a[child + 1]) < 0) {
                child++;
            }
            if (tmp.compareTo(a[child]) < 0) {
                a[i] = a[child];
            } else {
                break;
            }
        }
        a[i] = tmp;
    }

    private static int leftChild(int i) {
        return 2 * i + 1;
    }

    /**
     * 交換數組中兩個位置的元素
     *
     * @param a:目標數組
     * @param index1 :第一個元素下標
     * @param index2 :第二個元素下標
     * @param <T>
     */

    private static <T> void swapReferences(T[] a, int index1, int index2) {
        T tmp = a[index1];
        a[index1] = a[index2];
        a[index2] = tmp;
    }
}
//輸出結果
//原序列:[7, 1, 13, 9, 11, 5, 8]
//排序後:[1, 5, 7, 8, 9, 11, 13]
  • 時間複雜度:buildHeap使用O(N)的時間,元素下濾須要O(logN),須要下濾N-1次,因此總共須要O(N+(N-1)logN) = O(NlogN)。從過程能夠看出,堆排序,無論最好,最壞時間複雜度都穩定在O(NlogN)。app

  • 空間複雜度:使用自身存儲,無疑是O(1)ui

4、總結

本篇經過畫圖,說明堆排序的過程,清晰明瞭知道堆排序先通過堆序化,再經過deleteMax進行排序。其空間複雜度是O(1),時間複雜度穩定在O(NlogN)。spa

相關文章
相關標籤/搜索