首頁  >  文章  >  Java  >  Java學習之堆排序流程圖解以及程式碼講解

Java學習之堆排序流程圖解以及程式碼講解

little bottle
little bottle轉載
2019-04-28 10:03:332879瀏覽

本篇文章主要用圖片的形式講解了堆排序流程,之後用Java代碼實現堆排序並且分析時間複雜度,具有一定參考價值,有興趣的朋友可以了解一下。

一、導論

###################################################################################################################################################三、java程式碼實作及時間複雜度分析############四、總結###############一、引言####### # ########優先佇列可以用來以O(NlogN)時間排序,如同上一篇的解topK問題中所用到的想法一樣,這種想法就是堆排序(heapsort)。 #########二、圖解堆排序(heapsort)###### ################演算法思想:透過將陣列元素進行buildHeap進行堆序化(建造大頂堆);再對堆進行N-1次deleteMax操作。 ###這裡有個技巧,如果使用新的數組來存儲,需要O(N)的空間;但每次deleteMax會空出一個位置,並將尾端的節點進行下濾操作,那我們就可以將deleteMax的資料放到尾端。 #########堆排序過程:############對二元堆不了解的可以看看圖解優先隊列(堆)###

三、java程式碼實作及時間複雜度分析

我們從陣列下標0開始,不像二元堆從數組下標1開始。

  • 程式碼實作

  • public class Heapsort {
        public static void main(String[] args) {
            Integer[] integers = {7, 1, 13, 9, 11, 5, 8};
            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)。

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

四、總結

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

以上是Java學習之堆排序流程圖解以及程式碼講解的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文轉載於:cnblogs.com。如有侵權,請聯絡admin@php.cn刪除