1. 程式人生 > >排序算法(二):堆排序-Java實現

排序算法(二):堆排序-Java實現

並且 小頂堆 但是 清晰 big 又是 左右 位置 堆排

排序算法(二):堆排序-Java實現

首先對堆排序有個整體的認識,堆排序是一個不穩定的排序算法,其平均時間復雜度為O(nlogn),空間復雜度O(1)。

那麽何為堆排序呢?所謂堆排序是借助於堆的概念來完成的排序算法,其是選擇排序中的一種,因此通過選擇排序來理解堆排序會更加容易一些

下面我們來看一下堆的概念,其實堆又是借助於二叉樹的概念來定義,對於堆分為大頂堆和小頂堆兩種,下面用數學表示式來精確的描述如下:

假設我們使用array數組來存儲堆,因為大頂堆表述為 array[i] >=array[2*i+1] && array[i] >= array[2*1+2] , 小頂堆表示為array[i] <=array[2*i+1] && array[i] <= array[2*1+2], 但是值的註意的是array[2*i+1] 與array[2*i+2] 之間沒有大小約束關系

對於堆的基本定義我們已經很清晰了,下面我們將詳細的介紹一下堆排序的思路

堆排序的整體思路如下(以大頂堆為例說明,小頂堆同理哈)

  1. 根據大定堆的概念array[0]始終是最大的,因此與array[array.length-1]進行交換,此時就形成了 array[0].... array[array.length-2] 的無序數組和 array[array.length-1] 的有序數組
  2. 在1中形成的 array[0].... array[array.length-2] 無序數組中破壞了堆的特性,因此需要一次調整,調整從array.length-1處開始
    • 首先找到array.length-1 父親節點,如果有左右孩子,進行比較進行交換,依次循環往前進行處理

  3. 依照按照1,2步驟循環進行,直到排序完成

Java 實現代碼邏輯如下:

 1 public class HeapSort {
 2 
 3     public static void main(String[] args) {
 4         int[] array = new int[]{5, 3, 6, 2, 1, 9, 4, 8, 7};
 5 
 6         HeapSort heapSort = new HeapSort();
 7         heapSort.heapSort(array);
 8 
 9         for (int i = 0; i < array.length; i++) {
10 System.out.print(array[i]+" "); 11 } 12 } 13 14 15 public void heapSort(int[] array) { 16 17 for (int i = 0; i < array.length; i++) { 18 // 將array[array.length-1-i]創建為堆 19 createMaxHeap(array, array.length - 1 - i); 20 // 因為大頂堆,所以最大值始終處於array[0], 21 // 交換array[0]與array[array.length-1-i] 22 swap(array, 0, array.length - 1 - i); 23 } 24 } 25 26 // 調整成堆 27 private void createMaxHeap(int[] array, int lastIndex) { 28 // 從當前位置的父親節點 29 for (int i = (lastIndex - 1) / 2; i >= 0; i--) { 30 // 記錄當前的位置節點 31 int k = i; 32 // 條件成立,則說明有孩子節點,此時判斷是否滿足堆的特性 33 while (2 * k + 1 <= lastIndex) { 34 // 默認左孩子為最大 35 int biggerIndex = 2 * k + 1; 36 // 在判斷一下看是否有右孩子 37 if (biggerIndex < lastIndex) { 38 // 如果存在右孩子,並且右孩子大,則將默認索引加1 39 if (array[biggerIndex] < array[biggerIndex + 1]) { 40 biggerIndex++; 41 } 42 } 43 44 // 此時在跟父親節點作比較 45 if (array[k] < array[biggerIndex]) { 46 swap(array, k, biggerIndex); 47 } else { // 如果不小於則結束本次循環,下一個節點的比較 48 break; 49 } 50 } 51 } 52 } 53 54 // 交換兩個元素 55 private void swap(int[] data, int i, int j) { 56 if (i == j) { 57 return; 58 } 59 data[i] = data[i] + data[j]; 60 data[j] = data[i] - data[j]; 61 data[i] = data[i] - data[j]; 62 }

博客描述不對之處,請指正,希望給大家帶來幫助,謝謝。

排序算法(二):堆排序-Java實現