堆排序算法詳解


1、堆排序概述

堆排序(Heapsort)是指利用堆積樹(堆)這種數據結構所設計的一種排序算法,它是選擇排序的一種。可以利用數組的特點快速定位指定索引的元素。堆分為大根堆和小根堆,是完全二叉樹。大根堆的要求是每個節點的值都不大於其父節點的值,即A[PARENT[i]] >= A[i]。在數組的非降序排序中,需要使用的就是大根堆,因為根據大根堆的要求可知,最大的值一定在堆頂。

2、堆排序思想(大根堆)

1)先將初始文件Array[1...n]建成一個大根堆,此堆為初始的無序區。

2) 再將關鍵字最大的記錄Array[1](即堆頂)和無序區的最后一個記錄Array[n]交換,由此得到新的無序區Array[1..n-1]和有序區Array[n],且滿足Array[1..n-1].keys≤Array[n].key。

3)由於交換后新的根R[1]可能違反堆性質,故應將當前無序區R[1..n-1]調整為堆。然后再次將R[1..n-1]中關鍵字最大的記錄R[1]和該區間的最后一個記錄R[n-1]交換,由此得到新的無序區R[1..n-2]和有序區R[n-1..n],且仍滿足關系R[1..n-2].keys≤R[n-1..n].keys,同樣要將R[1..n-2]調整為堆。這樣直到無序區中剩余一個元素為止。

3、堆排序的基本操作

1)建堆,建堆是不斷調整堆的過程,從len/2處開始調整,一直到第一個節點,此處len是堆中元素的個數。建堆的過程是線性的過程,從len/2到0處一直調用調整堆的過程,相當於o(h1)+o(h2)…+o(hlen/2) 其中h表示節點的深度,len/2表示節點的個數,這是一個求和的過程,結果是線性的O(n)。

2)調整堆:調整堆在構建堆的過程中會用到,而且在堆排序過程中也會用到。利用的思想是比較節點i和它的孩子節點left(i),right(i),選出三者最大者,如果最大值不是節點i而是它的一個孩子節點,那邊交互節點i和該節點,然后再調用調整堆過程,這是一個遞歸的過程。調整堆的過程時間復雜度與堆的深度有關系,是lgn的操作,因為是沿着深度方向進行調整的。

3)堆排序:堆排序是利用上面的兩個過程來進行的。首先是根據元素構建堆。然后將堆的根節點取出(一般是與最后一個節點進行交換),將前面len-1個節點繼續進行堆調整的過程,然后再將根節點取出,這樣一直到所有節點都取出。堆排序過程的時間復雜度是O(nlgn)。因為建堆的時間復雜度是O(n)(調用一次);調整堆的時間復雜度是lgn,調用了n-1次,所以堆排序的時間復雜度是O(nlgn)

4、堆排序的實現(java)

  1 package com.arithmetic.demo;
  2 
  3 public class HeapSort {
  4     //交換元素
  5     public static void exchange(int[] array,int i,int j)
  6     {
  7         int temp = array[i];
  8         array[i] = array[j];
  9         array[j] = temp;        
 10     }
 11     //獲得父節點
 12     public static int parentNode(int i)
 13     {
 14         return (i - 1)/2;
 15     }
 16     //獲得左節點
 17     public static int leftNode(int i)
 18     {
 19         return 2*i + 1;
 20     }
 21     //獲得右節點
 22     public static int rightNode(int i)
 23     {
 24         return 2*i + 2;
 25     }
 26     //最大堆
 27     public static void maxHeap(int[] array,int heapSize,int index)
 28     {
 29         int left = leftNode(index);
 30         int right = rightNode(index);
 31         int largeNode = index;
 32         if(left < heapSize && array[left] > array[largeNode])
 33         {
 34             largeNode = left;
 35         }
 36         if(right < heapSize && array[right] > array[largeNode])
 37         {
 38             largeNode = right;
 39         }
 40         if(index != largeNode)
 41         {
 42             exchange(array, index, largeNode);
 43             maxHeap(array,heapSize,largeNode);
 44         }
 45     }
 46     public static void buildHeap(int[] array)
 47     {
 48         if(array == null || array.length <= 1){
 49             return;
 50         }
 51         int half = array.length/2;
 52         for(int i=half;i>=0;i--)
 53         {
 54             maxHeap(array,array.length,i);
 55         }
 56     }
 57     public static void heapSort(int[] array)
 58     {
 59         if(array == null || array.length <= 1)
 60         {
 61             return;
 62         }
 63         buildHeap(array);
 64         for(int i=array.length -1;i>=1;i--)
 65         {            
 66             exchange(array,0,i);
 67             maxHeap(array,i,0);
 68         }
 69     }
 70     public static void printHeapTree(int[] array)
 71     {
 72         for(int i=1;i<=array.length;i=i*2)
 73         {
 74             for(int k=i-1;k<2*i-1 && k<array.length;k++)
 75             {
 76                 System.out.print(array[k]+" ");
 77             }
 78             System.out.println();
 79         }
 80     }
 81     public static void printHeap(int[] array)
 82     {
 83         for(int i=0;i<array.length;i++)
 84         {
 85             System.out.print(array[i]+" ");
 86         }
 87     }
 88     public static void main(String[] args)
 89     {
 90         int[] array = {7,4,5,3,2,6,9,1};
 91         System.out.println("執行最大堆化前,堆結構:");
 92         printHeapTree(array);
 93         
 94         buildHeap(array);
 95         
 96         System.out.println("執行最大堆化后,堆結構:");
 97         printHeapTree(array);
 98         
 99         heapSort(array);
100         
101         System.out.println("堆排序結果:");
102         printHeap(array);
103     }
104 
105 }

5、算法分析

堆排序的時間,主要由建立初始堆和反復重建堆這兩部分的時間開銷構成,它們均是通過調用buildHeap實現的。它是不穩定的排序方法。平均性能:O(N*logN)。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM