本文提供了一种基于分治法思想的,查找第K个大的数,可以使得时间复杂地低于nlogn. 因为快排的平均时间复杂度为nlogn,但是快排是全部序列的排序,
本文查找第k大的数,则不必对整个序列进行排序。请看本文:
说明本文为原创文章,转载请注明出自:丰泽园的天空-快速排序及查找第K个大的数
1 #include<stdio.h> 2 #include<stdlib.h> 3 /* 如何查找第k小的数,或者第k大的数*/ 4 partition(int data[],size_t left ,size_t right) 5 { 6 int i = left; 7 int j = right; 8 int p = (left + right) / 2; 9 int pivot = data[p]; 10 while(i < j){ 11 for(; i < p && data[i] <= pivot;++i); 12 if(i < p) { 13 data[p] = data[i]; 14 p = i; 15 } 16 for(; j > p && data[j] >= pivot; --j); 17 if( j > p){ 18 data[p] = data[j]; 19 p = j; 20 } 21 } 22 data[p] = pivot; 23 return p; 24 25 } 26 int quick_sort(int data[],size_t left, size_t right) 27 { 28 if(left < right){ 29 int index = partition(data,left,right); 30 if(index - left > 1 ) 31 quick_sort(data,left, index-1); 32 if(right - index > 1) 33 quick_sort(data,index + 1, right); 34 35 } 36 37 } 38 int findK(int data[], size_t left, size_t right, size_t k){ 39 if(left < right){ 40 int mid = partition(data,left, right); 41 if(mid - left + 1 >= k) 42 findK(data,left, mid, k ); 43 else 44 findK(data, mid + 1, right, k- (mid - left +1)); 45 } 46 47 } 48 int main() 49 { 50 int data[] = {12,2,1 ,0 ,4,11,-1, 9 ,6}; 51 int len = sizeof(data)/sizeof(data[0]); 52 // quick_sort(data,0,len - 1); 53 int i =0; 54 /* 打印原始序列 */ 55 for( i = 0; i < len ; ++i) 56 { 57 printf(" %d ",data[i]); 58 } 59 findK(data,0,len - 1, 5); 60 printf("x = %d ", data[5] ); 61 /* 找到第k个大的数后,序列的变化为:---快排之前*/ 62 for( i = 0; i < len ; ++i) 63 { 64 printf(" %d ",data[i]); 65 } 66 printf(" "); 67 /* 快排之后的序列*/ 68 quick_sort(data,0,len - 1); 69 for( i = 0; i < len ; ++i) 70 { 71 printf(" %d ",data[i]); 72 } 73 printf(" "); 74 75 }
说明:查找第K个大的数,用到是分治法的思想。联想到快排中,完成一次排序,左边的序列比基准值小,右边的序列比基准值大,只要确定第k个大数在哪个序列中,只要对这个子序列进行排序即可。
最新评论