思路解法详见代码中的注释部分,写得应该算比较详细了~ /********************问题描述************************ 有若干个无序的数(假设数目为N),如何选择其中最大的 K个数 *****************************************************/ #include<iostream> #include<algorithm> #include<functional> using namespace std; /***********************解法一:全部排序************** 将输入的N的数排序,然后选出前K个数,使用快排算法,时间 复杂度是O(NlogN),输出的结果由大到小排序 ******************************************************/ void FindTopK1(int *a,int len,int k){ // const int len=sizeof(a)/sizeof(int); if(k>len){ cout<<"Error! The "<<k<<" is larger than the length of array!"<<endl; return ; } sort(a,a+len,greater<int>()); } /************************解法二:部分排序************** 使用选择排序,每一轮找出该轮最大的数,放到相应的位置, 一共需要K轮,时间复杂度为N*K,输出结果由大到小排序 ******************************************************/ void FindTopK2(int *a,int len,int k){ if(k>len){ cout<<"Error! The "<<k<<" is larger than the length of array!"<<endl; return ; }else if(k==len){ cout<<"The top "<<k<<" is the whole array!"<<endl; } for(int i=0;i<k;i++){ int Largest=i; for(int j=i;j<len;j++){ if(a[Largest]<a[j]){ //交换a[Largest]跟a[j]的值 int tmp=a[Largest]; a[Largest]=a[j]; a[j]=tmp; } } } } /************************解法三:快速选择***************** 函数定义为FindTopK3(int *a,int left,int right,int k)类似于 快排的思想,定义一个partition函数,返回一个pivot,如果pivot 小于k,则在数组位置pivot跟right中调用函数 FindTopK3(a,pivot+1,right,k-pivot), 如果pivot大于k,则在数组位置left跟pivot-1中调用FindTopK3(a,left,pivot-1,k) 如果pivot等于k,则数组a[0..k]即为所求,但是在这部分数据中数据是无序的, 时间复杂度小于nlogn **********************************************************/ int Partition(int *a,int left,int right){ int i=left; int j=right; int temp=a[j]; while(i!=j){ while((a[i]>=temp)&&(i<j)) i++; if(i<j){ a[j]=a[i]; j--; } while((a[j]<=temp)&&(i<j)) j--; if(i<j){ a[i]=a[j]; i++; } } a[i]=temp; return i; } void FindTopK3(int *a,int left,int right,int k){ if(right<=left) return; int pivot=Partition(a,left,right); if(k<=pivot){ FindTopK3(a,left,pivot-1,k); }else{ FindTopK3(a,pivot+1,right,k-pivot); } } /***********************解法四:建堆*************************** 利用前k个数建立一个大小为k的最小堆,然后对第k+1~n个数,每次将其 跟最小堆里面的最小元素进行比较,假设比最小堆的最小元素还小的话则 直接排除,假设大的话弹出最小堆的最小元素并加入该元素然后重新建 堆,总用时为N*logK **************************************************************/ void FindTopK4(int *a,int len,int k){ make_heap(a,a+k,greater<int>()); for(int i=k;i<len;i++){ if(a[i]>a[0]){ int tmp=a[0]; a[0]=a[i]; a[i]=tmp; make_heap(a,a+k,greater<int>()); } } } /**********************解法五:利用桶排序的思想***************** 当数组中包含很多重复元素并且重复元素的取值在一定的范围内,可以采 用桶排序,先使用一个数组count[i]记录每个元素i出现的次数,然后定义 一个sumCount,i从N-1到0,有sumCount+=count[i],当sumCount等于K的 时候停止,该方法时间复杂度是线性的,空间复杂度较高 ****************************************************************/ #define MAIN #ifdef MAIN int main(){ int a[]={5,6,8,3,7,9}; int k=4; // FindTopK1(a,6,4); // FindTopK2(a,6,k); // FindTopK3(a,0,5,k); FindTopK4(a,6,k); cout<<"The top K is; "<<endl; for(int i=0;i<k;i++) cout<<a[i]<<" "; cout<<endl; system("PAUSE"); return 0; } #endif