您的位置:首页 > 其它

求N个数中最大的K个数的几种方法与实现

2011-04-09 19:11 357 查看
某笔试题:内存中有一个长数组,有100W条记录, 每个记录为一个struct array, sizeof( array ) = 512, 在这个struct里有一个int型成员变量weight, 现要取得按个weight值从大到小排序的前500个数组单元(求N里的前K个大的数)
直接贴代码吧,废话少讲(先说方法吧)~~~~解释在注释里:)
const static long N = 10000000;
const static long K = 100;
static long cnt;
struct Elem
{
Elem()
{
  weight = rand()%100000;
}
long weight;
//char data[512];
};
void main()
{
srand(time(NULL));
//直接用数据会越过程序初始栈大小,所在要在堆里申请空间~~~运行时可以断一下点,看一下任务管理器占用多少内存
Elem  * p = new Elem
;
long take = GetTickCount();  
//time_t   first,   second; 
//first   =   time(NULL);     /*   Gets   system */
//方法一
//先将最大的k个交换到前面,再对其全排
DirectSearch( p, K );
QuickSort( p, 0, K - 1 );
PrintElem( p, K );
//方法二
//先用半快排,求出长度为k的区间后,再对其全排
//  PartQuickSort( p, 0, N - 1, K );
//  QuickSort( p, 0, K - 1 );
//  PrintElem( p, K );
//方法三
//用一个小根堆保存这k个数, 遍历一次即可,每次与第一个比较, 如果更新了就调整
//HeapK( p, K );
//估计做出以上三种方法的实现,面试官都基本满意啦,一般软件公司的offer也是八九不离十了.
//但是,继续还有方法...
//解法四: 如果加上限制条件(1) 所有数为整数 (2) 所有数的变化范围不大 这样就可以利用记数排序法的思想
//Countsort( p, K )
//second   =   time(NULL);   /*   Gets   system   time    again   */
cout<<"tick="<< GetTickCount() - take <= mid.weight )   
            i++;  
        if( i WArray[ j +1 ] )  
            j++;  
        if( WArray[j] < WArray[(j-1)/2] )  
        {  
            change = true;  
            t = WArray[(j-1)/2];  
            WArray[(j-1)/2] = WArray[j];  
            WArray[j] = t;  
        }  
    }  
    return change;  
}  
void MinHeap( int * WArray, int len )  
{  
    if( len <= 0 )  
        return;  
    //根据堆的性质: 左孩子为 2i +1 , 右孩为 2i + 2( 因为从0开始计数 )  
    int i;  
    //从最后一个有孩子的结点开始,向前调整  
    len--;  
    for( i = (len-1)/2; i >=0; i-- )  
        AdjHeap( WArray, i, len );  
}  
//解法四: 如果加上限制条件(1) 所有数为整数 (2) 所有数的变化范围不大 这样就可以利用记数排序法的思想  
//遍历一次N, 找出最大值MAX  
//开一个数组 T[MAX];   
//再遍历一次N, 对每个数计数 T[ A[i] ]++; ( 0<= i <= N )   
//由于是求前K个最大的数,所以就可以从后面起取  
void Countsort( Elem * src, int k )  
{  
    long i,j;  
    int max;  
    int wt;  
    int * kArray = new int[k];  
    long take = GetTickCount();    
    //遍历一次N, 找出最大值MAX  
    max = src[0].weight;  
    for( i=0; i0 ; i-- )  
    {  
        //跳过没有的数  
        if( !T[i] )  
            continue;  
        if( T[i] >= n )  
        {  
            //保存结果在另一个数组,以免影响计算时间  
            for( j =0; j= mid.weight )
   i++;
  if( i WArray[ j +1 ] )
   j++;
  if( WArray[j] < WArray[(j-1)/2] )
  {
   change = true;
   t = WArray[(j-1)/2];
   WArray[(j-1)/2] = WArray[j];
   WArray[j] = t;
  }
}
return change;
}
void MinHeap( int * WArray, int len )
{
if( len <= 0 )
  return;
//根据堆的性质: 左孩子为 2i +1 , 右孩为 2i + 2( 因为从0开始计数 )
int i;
//从最后一个有孩子的结点开始,向前调整
len--;
for( i = (len-1)/2; i >=0; i-- )
  AdjHeap( WArray, i, len );
}
//解法四: 如果加上限制条件(1) 所有数为整数 (2) 所有数的变化范围不大 这样就可以利用记数排序法的思想
//遍历一次N, 找出最大值MAX
//开一个数组 T[MAX];
//再遍历一次N, 对每个数计数 T[ A[i] ]++; ( 0<= i <= N )
//由于是求前K个最大的数,所以就可以从后面起取
void Countsort( Elem * src, int k )
{
long i,j;
int max;
int wt;
int * kArray = new int[k];
long take = GetTickCount(); 
//遍历一次N, 找出最大值MAX
max = src[0].weight;
for( i=0; i0 ; i-- )
{
  //跳过没有的数
  if( !T[i] )
   continue;
  if( T[i] >= n )
  {
   //保存结果在另一个数组,以免影响计算时间
   for( j =0; j
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: