該題目的兩種實現方式,第一種是用堆排序(其中數組用到了二叉樹的性質),第二種是利用快速排序來實現.算法
最大堆進行升序排序,主要步驟是數組
1.初始化堆:將數列a[1...n]構形成最大堆。dom
2.交換數據:將a[1]和a[n]交換,使a[n]是a[1...n]中的最大值;而後將a[1...n-1]從新調整爲最大堆。 接着,將a[1]和a[n-1]交換,使a[n-1]是a[1...n-1]中的最大值;而後將a[1...n-2]從新調整爲最大值。 依次類推,直到整個數列都是有序的。spa
1 static void Swap<T>(ref T t1, ref T t2) { 2 T temp = t1; 3 t1 = t2; 4 t2 = temp; 5 } 6 7 static void Maxheap_Down(int[] arr, int start, int end) { 8 9 int current = start; 10 int left = 2 * current + 1; 11 int temp = arr[current]; 12 13 for (; left <= end; current = left, left = 2 * left + 1) { 14 if (left < end && arr[left] < arr[left + 1]) { 15 left++; 16 } 17 if (temp >= arr[left]) 18 break; 19 else { 20 arr[current] = arr[left]; 21 arr[left] = temp; 22 } 23 } 24 } 25 26 static int Heap_Find_NumberK(int[] arr, int k) { 27 int n = arr.Length; 28 int i; 29 30 for (i = n / 2 - 1; i >= 0; i--) { 31 Maxheap_Down(arr, i, n - 1); 32 } 33 34 for (i = n - 1; i >= k-1; i--) { 35 Swap(ref arr[0], ref arr[i]); 36 Maxheap_Down(arr, 0, i - 1); 37 } 38 return arr[k - 1]; 39 }
堆排序時間複雜度
堆排序的時間複雜度是O(N*lgN)。
假設被排序的數列中有N個數。遍歷一趟的時間複雜度是O(N),須要遍歷多少次呢?
堆排序是採用的二叉堆進行排序的,二叉堆就是一棵二叉樹,它須要遍歷的次數就是二叉樹的深度,而根據徹底二叉樹的定義,它的深度至少是lg(N+1)。最可能是多少呢?因爲二叉堆是徹底二叉樹,所以,它的深度最多也不會超過lg(2N)。所以,遍歷一趟的時間複雜度是O(N),而遍歷次數介於lg(N+1)和lg(2N)之間;所以得出它的時間複雜度是O(N*lgN)。code
利用快排劃分出來的主元位置再遞歸尋找,這種方法叫做隨機選擇算法。它對任何輸入均可以達到O(n)的指望時間複雜度。xml
1 static int RandPartition(int[] arr, int left, int right) { 2 Random rd = new Random(); 3 int p = rd.Next(left, right + 1); 4 Swap(ref arr[p], ref arr[left]); 5 int temp = arr[left]; 6 while (left < right) { 7 while (left < right && arr[right] > temp) { right--; count++; } 8 arr[left] = arr[right]; 9 while (left < right && arr[left] <= temp) { left++; count++; } 10 arr[right] = arr[left]; 11 } 12 arr[left] = temp; 13 return left; 14 } 15 16 static int RandSelect(int[] arr, int left, int right, int k) { 17 if (left == right) { 18 return arr[left]; 19 } 20 int index = RandPartition(arr, left, right); 21 int M = index + 1; 22 if (M == k) { 23 return arr[index]; 24 } 25 int result = -1; 26 if (M < k) { 27 result = RandSelect(arr, index + 1, right, k); 28 } 29 else if (M > k) { 30 result = RandSelect(arr, left, index - 1, k); 31 } 32 return result; 33 }