网上看到一个面试题, 题目是这样的:在一百万个浮点数据中找到前100个最大的数!由于数据结构的知识在大学期间没有开专业的课程,而只是在工作后陆陆续续学习了些,很多学得不扎实。因此借这个机会把排序的10来种算法好好学习了下。
借鉴《编程之美》的分析思路,我把这个算法用c代码实际实现了下。详细请看源代码:
#include <stdio.h>
#include <stdlib.h>
#define NUM 1000000 //百万大军过江
#define MAX_AHEAD 100 //找出前100者
int adjust( int b[], int beg, int end )
{
int i,j,t;
t = b[beg];
i = beg;
j = i*2 + 1;
while( j < end )
{
if( j < end-1 )
{
if( b[j] > b[j+1] )
j++;
}
if( t < b[j] )
break;
b[ (j-1)/2 ] = b[j];
j = j*2 + 1;
}
j = ( j-1 ) / 2;
b[j] = t;
return 1;
}
int main( void )
{
int *a,*b;
long i;
a = ( int * )malloc( sizeof ( int ) * NUM );
b = ( int * )malloc( sizeof ( int ) * MAX_AHEAD );
for( i = 0; i < NUM; i++ )
{
a[i] = ( rand() % NUM );
// printf( "%d ", a[i] );
// if( ( i+1 ) % 20 == 0 )
// printf( "/n" );
}
//组建一个MAX_AHEAD大小数组
for( i = 0; i < MAX_AHEAD; i++ )
{
b[i] = a[i];
}
//将这MAX_AHEAD大小的数组组成最小堆二叉完全树
for( i = MAX_AHEAD / 2 - 1; i >= 0; i-- )
{
adjust( b, i, MAX_AHEAD );
}
//将后面的数据与二叉树最顶端那个最小值做比较
//如果比MAX_AHEAD中最小的还大的话就插进去,否则就跳过
//这样下来,它的整个复杂度就会降低很多
//大小为:O( n*long( MAX_AHEAD )
for( i = MAX_AHEAD; i < NUM; i++ )
{
if( a[i] > b[0] )
{
b[0] = a[i];
adjust( b, 0, MAX_AHEAD );
}
}
printf( "前%d个最大的值:/n",MAX_AHEAD );
for( i = 0; i < MAX_AHEAD; i++ )
{
printf( "%d ", b[i] );
if( (i+1) % 20 == 0 )
printf( "/n" );
}
if( a )
free( a );
if( b )
free( b );
return 0;
}