这是一道经常被人们忽视的题,因为我想会写冒泡排序的人应该都会做这一道题。先给这N个数来一个排序若是求最大的K个数就从大到小排序,若是求最小的数就从小到大排序,然后来一个循环输出前K个数就行了。好像是很简单,但大家没有想到的是,当数非常之多的时候,排序的效率就很低了,所以得想另外的方法。

此题完全可以用堆的特性来完成,建立一个含有K个结点的堆,若要求的是最大的K个数则建立小顶堆,遍历N个数时将每个数和堆顶的数比较,若大于堆顶数则替换掉堆顶的数,然后将堆重新恢复成小顶堆,当N个数遍历结束过后,堆里的K个数就是我们想要得到的数了。

 以下是源代码:

adjust( )负责调整数组a的 pos位置,使数组a重新变成一个堆。

maxk(int *a,int len,int k)表示求a中的最大的k个数。len为a的长度。

  1. void adjust(int *a,int pos,int len)  
  2. {  
  3.     int i,temp,temp1;  
  4.     i=pos;  
  5.     while(1)  
  6.     {  
  7.         if((2*i)+1<len)  
  8.         {  
  9.             if(2*i+2<len)  
  10.             {  
  11.                 temp=a[2*i+1]<a[2*i+2]?2*i+1:2*i+2;  
  12.                 if(a[i]>a[temp])  
  13.                 {  
  14.                     temp1=a[temp];  
  15.                     a[temp]=a[i];  
  16.                     a[i]=temp1;  
  17.                     i=temp;  
  18.                 }  
  19.                 else 
  20.                 {  
  21.                     break;  
  22.                 }  
  23.             }  
  24.            else 
  25.            {  
  26.                 if(a[i]>a[2*i+1])  
  27.                 {  
  28.                     temp=a[2*i+1];  
  29.                     a[2*i+1]=a[i];  
  30.                     a[i]=temp;  
  31.                     i=2*i+1;  
  32.                 }  
  33.                 else 
  34.                 {  
  35.                     break;  
  36.                 }  
  37.             }  
  38.         }  
  39.         else break;  
  40.  
  41.     }  
  42. }  
  43. void maxk(int *a,int len,int k)  
  44. {  
  45.     int i,j;  
  46.     int *b=(int *)malloc(k*sizeof(int));  
  47.     memset(b,0,k);  
  48.     for(i=0;i<len;i++)  
  49.     {  
  50.         if(a[i]>b[0])  
  51.         {  
  52.             b[0]=a[i];  
  53.             adjust(b,0,k);  
  54.         }  
  55.     }  
  56.     for(j=0;j<k;j++)  
  57.     {  
  58.         printf("%d ",b[j]);  
  59.     }