經典排序算法之:堆排序

背景及原理

1991年的計算機先驅獎獲得者、斯坦福大學計算機科學系教授羅伯特·弗洛伊德(Robert W.Floyd)和威廉姆斯(J.Williams)在1964年共同發明了著名的堆排序算法( Heap Sort )。堆排序(Heapsort)是指利用堆積樹(堆)這種數據結構所設計的一種排序算法,它是選擇排序的一種。可以利用數組的特點快速定位指定索引的元素。堆分爲大根堆和小根堆,是完全二叉樹。大根堆的要求是每個節點的值都不大於其父節點的值,即A[PARENT[i]] >= A[i]。在數組的非降序排序中,需要使用的就是大根堆,因爲根據大根堆的要求可知,最大的值一定在堆頂。

算法思路

基本思路:

這裏寫圖片描述
上圖的左圖是堆的構造過程,右圖是下沉操作。堆排序的主要操作在第二階段完成。這裏我們將堆最大元素刪除然後放入堆縮小後空出的位置中。我們發現,這個過程與選擇排序很相似,但是需要的比較次數要少得多。

程序實現:

package algs;

public class HeapSort {
     //堆排序核心算法
     public static void sort(Comparable[] pq) {
        int n = pq.length;
        //創建堆
        for (int k = n/2; k >= 1; k--)
            sink(pq, k, n);
        //銷燬堆
        while (n > 1) {
            exch(pq, 1, n--);//把找到的最大的數交換到最後。
            sink(pq, 1, n);//把第一個數放到合適的位置,構建堆。
        }
     }

     //下沉
     private static void sink(Comparable[] pq, int k, int n) {
         while (2*k <= n) {
             int j = 2*k;
             if (j < n && less(pq, j, j+1)) j++;
             if (!less(pq, k, j)) break;
             exch(pq, k, j);
             k = j;
         }
     }

     //判斷大小
     private static boolean less(Comparable[] pq, int i, int j) {
         return pq[i-1].compareTo(pq[j-1]) < 0;
     }

    //交換元素
     private static void exch(Object[] pq, int i, int j) {
         Object swap = pq[i-1];
         pq[i-1] = pq[j-1];
         pq[j-1] = swap;
     }

    //打印輸出
    private static void show(Comparable[] a) {
         for (int i = 0; i < a.length; i++) {
            System.out.print(a[i]+" "); 
         }
         System.out.println();
     } 

    //測試用例
    public static void main(String[] args) {
        Comparable[] a = new Comparable[]
                {'B','F','S','R','T','J','D','A','Z','V','Y','H','K','I','P','Q','C','G','N','U','M','E','O'};
        System.out.print("排序前:");
        show(a);
        System.out.print("排序後:");
        HeapSort.sort(a);
        show(a);

    }
}

[程序輸出]

排序前:B F S R T J D A Z V Y H K I P Q C G N U M E O
排序後:A B C D E F G H I J K M N O P Q R S T U V Y Z

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章