標籤:改進 時間 mic partition printf ret .com 快排 遞迴
——本文為博主原創,轉載請註明出處
因為最近做的WSN(wireless sensor network)實驗要求用3個感應器節點接受2000個包的資料並算出一些統計量,其中就有算出中位元這麼一個要求,且其按算出資料的時間長短排名給分,所以就在考慮一個線性時間的求第k大小的數的演算法。
鑒於感應器只有10k的記憶體,以及考慮到快排的過程利於簡化,所以採用快速排序(以及由之前課程中做的排序演算法的測試得知,快排在相同時間複雜度的排序中有較大的優越性,最重要的就是快排好寫)。
演算法基本思想
快速排序的思想就不做過多的描述了,我們對之進行的改進是,每一趟劃分過後,把我們要找的第k位與作為基準數的下標進行比較,如果k大,就在基準數右邊的子數組中找,反之就在左邊的子數組中找。這樣就相當於每次快排過後對左右子數組的雙遞迴被最佳化成了單側的遞迴。
時間複雜度
考慮極端情況,假設數組大小n足夠大,在尋找的最後一趟(記為第m趟)才找到,第一趟沒找到為O(n),第二趟沒找到為O(n/2),第m趟沒找到為O(n/2m-1),時間複雜度為O(n(1+1/2+....+1/2m-1)),其中1,1/2,....,1/2m-1為q小於1的等比數列,求和的值是個常數設為C(由∑1/2k的收斂性知),則O(n(1+1/2+....+1/2m-1))=O(nC)=O(n)
代碼
因為感應器的代碼需要用nesC寫,所以程式採用C語言實現
1 #include <stdio.h> 2 3 int partition(int *a, int low, int high) 4 { 5 int pivot = a[low]; 6 while (low < high) 7 { 8 while (a[high] >= pivot && low < high) 9 high--;10 a[low] = a[high];11 12 while (a[low] <= pivot && low <high)13 low++;14 a[high] = a[low];15 }16 a[low] = pivot;17 return low;18 }19 20 int quickSortKth(int *a, int low, int high, int k)21 {22 if (low >= high)23 return a[low];24 else25 {26 int mid = partition(a, low, high);27 if (mid > k)28 quickSortKth(a, low, mid - 1, k);29 else if (mid < k)30 quickSortKth(a, mid + 1, high, k);31 else32 return a[mid];33 }34 }35 36 int getKthMax(int *a, int k, int len) {37 return quickSortKth(a, 0, len - 1, len-k);38 }39 40 int getKthMin(int *a, int k, int len) {41 return quickSortKth(a, 0, len - 1, k-1);42 }43 44 int main()45 {46 int a[15] = { 13,7,8,6,3,10,11,14,15,12,1,5,2,4,9 };47 int k;48 int len = sizeof(a) / sizeof(a[0]);//擷取數組a的大小49 scanf("%d", &k);50 //printf("%d", len);51 printf("result: %d\n", getKthMin(a, k, len));52 return 0;53 }
結果
三花
2016-12-25
線性時間O(n)內求數組中第k大小的數