從無序數組中找出第K大的數

該題目的兩種實現方式,第一種是用堆排序(其中數組用到了二叉樹的性質),第二種是利用快速排序來實現.算法

第一種:堆排序

最大堆進行升序排序,主要步驟是數組

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         }
相關文章
相關標籤/搜索