这是一道经常被人们忽视的题,因为我想会写冒泡排序的人应该都会做这一道题。先给这N个数来一个排序若是求最大的K个数就从大到小排序,若是求最小的数就从小到大排序,然后来一个循环输出前K个数就行了。好像是很简单,但大家没有想到的是,当数非常之多的时候,排序的效率就很低了,所以得想另外的方法。
此题完全可以用堆的特性来完成,建立一个含有K个结点的堆,若要求的是最大的K个数则建立小顶堆,遍历N个数时将每个数和堆顶的数比较,若大于堆顶数则替换掉堆顶的数,然后将堆重新恢复成小顶堆,当N个数遍历结束过后,堆里的K个数就是我们想要得到的数了。
以下是源代码:
adjust( )负责调整数组a的 pos位置,使数组a重新变成一个堆。
maxk(int *a,int len,int k)表示求a中的最大的k个数。len为a的长度。
- void adjust(int *a,int pos,int len)
- {
- int i,temp,temp1;
- i=pos;
- while(1)
- {
- if((2*i)+1<len)
- {
- if(2*i+2<len)
- {
- temp=a[2*i+1]<a[2*i+2]?2*i+1:2*i+2;
- if(a[i]>a[temp])
- {
- temp1=a[temp];
- a[temp]=a[i];
- a[i]=temp1;
- i=temp;
- }
- else
- {
- break;
- }
- }
- else
- {
- if(a[i]>a[2*i+1])
- {
- temp=a[2*i+1];
- a[2*i+1]=a[i];
- a[i]=temp;
- i=2*i+1;
- }
- else
- {
- break;
- }
- }
- }
- else break;
- }
- }
- void maxk(int *a,int len,int k)
- {
- int i,j;
- int *b=(int *)malloc(k*sizeof(int));
- memset(b,0,k);
- for(i=0;i<len;i++)
- {
- if(a[i]>b[0])
- {
- b[0]=a[i];
- adjust(b,0,k);
- }
- }
- for(j=0;j<k;j++)
- {
- printf("%d ",b[j]);
- }
- }