算法導論---第6章---堆排序ios
一、堆排序簡介算法
堆排序(heapsort)。與歸併排序同樣,但不一樣於插入排序的是,堆排序的時間複雜度是O(nlgn)。而與插入排序相同,但不一樣于歸並排序的是,堆排序一樣具備空間原址性:任什麼時候候都只須要常數個額外的元素存儲臨時數據。所以,堆排序是集合了插入排序和歸併排序這兩種排序算法優勢的一種排序算法。api
二、基本過程數組
MAX-HEAPIFY過程:其時間複雜度爲O(lgn),它是維護最大堆性質的關鍵。ui
BUILD-MAX-HEAP過程:具備線性時間複雜度,功能是從無序的輸入數據數組中構造一個最大堆。spa
HEAPSORT過程:其時間複雜度爲O(nlgn),功能是對一個數組進行原址排序。code
三、算法描述blog
首先,堆排序算法利用BUILD-MAX-HEAP將輸入數組A[1...n]建成最大堆,其中n=A.length。由於數組中的最大元素總在根節點A[1]中,經過把它與A[n]進行互換,咱們可讓該元素放到正確的位置。這時候,若是咱們從堆中去掉節點n(這一操做能夠經過減小A.heap-size的值來實現),剩餘的節點中,原來根的孩子節點仍然是最大堆,而新的根節點可能會違背最大堆的性質。爲了維護最大堆的性質,咱們要作的是調用MAX-HEAPIFY(A, 1),從而在A[1...n-1]上構造一個新的最大堆。堆排序算法會不斷重複這一過程,知道堆得大小從n-1降到2.排序
算法僞代碼描述以下:it
PARENT(i)
1 return ⌊i/2⌋
LEFT(i)
1 return 2i
RIGHT(i)
1 return 2i+1
MAX-HEAPIFY(A, i)
1 l = LEFT(i)
2 r = RIGHT(i)
3 if l ≤ A.heap-size and A[l] > A[i]
4 largest = l
5 else largest = i
6 if r ≤ A.heap-size and A[r] > A[largest]
7 largest = r
8 if largest ≠ i
9 exchange A[i] with A[largest]
10 MAX-HEAPIFY(A, largest)
BUILD-MAX-HEAP(A)
1 A.heap-size = A.length
2 for i = ⌊A.length/2⌋ downto 1
3 MAX-HEAPIFY(A, i)
HEAPSORT(A)
1 BUILD-MAX-HEAP(A)
2 for i = A.length downto 2
3 exchange A[1] with A[i]
4 A.heap-size = A.heap-size - 1
5 MAX-HEAPIFY(A, 1)
四、算法代碼(C++實現)
ps:由於僞碼中數組A的起始小標爲1,而實際編寫C++代碼中,數組的起始下標爲0,因此這裏要注意計算父節點、子節點的下標公式與僞碼中不一樣,同時須要注意循環體的結束條件也與僞碼中略有差別。
1 #include <iostream> 2 #include <math.h> 3 #include <stdio.h> 4 5 using namespace std; 6 7 inline int PARENT(int i) {return (i+1)/2 - 1;}; 8 inline int LEFT(int i) {return 2*i+1;}; 9 inline int RIGHT(int i) {return (2*i+2);}; 10 11 void Max_Heapify(int *a, int length, int i); 12 void Max_BuildHeap(int *a, int length); 13 void Max_HeapSort(int *a, int length); 14 15 int main() 16 { 17 int a[] = {4, 1, 3, 2, 16, 9, 10, 14, 8, 7}; 18 int length = 10; 19 20 Max_HeapSort(a, length); 21 22 cout << "Result of Max_HeapSort(): " << endl; 23 for (int i = 0; i < length; i++) 24 { 25 cout << a[i] << " "; 26 } 27 cout << endl; 28 29 return 0; 30 } 31 32 33 void exchange(int &a, int &b) 34 { 35 // 交換變量 a 和 b 的值 36 if (a == b) 37 { 38 return; 39 } 40 int tmp = a; 41 a = b; 42 b = tmp; 43 } 44 45 void Max_Heapify(int a[],int length, int i) 46 { 47 // 對數組 a 的第 i 個元素進行堆化操做 48 if (a == NULL) 49 { 50 cerr << "Max_Heapify(): Array is NULL!" << endl; 51 return; 52 } 53 int heap_size = length; 54 55 int l = LEFT(i); 56 int r = RIGHT(i); 57 int largest; 58 59 if (l < heap_size && a[l] > a[i]) 60 { 61 largest = l; 62 } 63 else 64 { 65 largest = i; 66 } 67 if (r < heap_size && a[r] > a[largest]) 68 { 69 largest = r; 70 } 71 if(largest != i) 72 { 73 exchange(a[i], a[largest]); 74 Max_Heapify(a, length, largest); 75 } 76 } 77 78 void Max_BuildHeap(int a[], int length) 79 { 80 // 創建最大堆 81 if (a == NULL) 82 { 83 cerr << "Max_BuildHeap(): Array is NULL!" << endl; 84 return; 85 } 86 for (int i = floor((length-1)/2); i >= 0; i--) 87 { 88 Max_Heapify(a, length, i); 89 } 90 } 91 92 void Max_HeapSort(int a[], int length) 93 { 94 // 最大堆排序 95 if (a == NULL) 96 { 97 cerr << "Max_HeapSort(): Array is NULL!" << endl; 98 return; 99 } 100 int heap_size = length; 101 Max_BuildHeap(a, length); 102 103 cout << "Result of Max_BuildHeap(): " << endl; 104 for (int i = 0; i < length; i++) 105 { 106 cout << a[i] << " "; 107 } 108 cout << endl; 109 110 for (int i = length-1; i >= 1; i--) 111 { 112 exchange(a[0], a[i]); 113 heap_size -= 1; 114 Max_Heapify(a, heap_size, 0); 115 } 116 }
運行結果以下: