某笔试题:内存中有一个长数组,有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[N];
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 < cout<<"count="<< cnt <
//cout<<"tick="<< difftime(second,first)<
delete p;
}
下面者是实现~~~
-
-
-
- void DirectSearch( Elem * src, int k )
- {
-
- long i =0, j, l,idx;
-
- long max;
- Elem t;
- for( l=0; l
- {
- max = src[l].weight;
- for( j=l; j
- {
- if( max < src[j].weight )
- {
- max = src[j].weight;
- idx = j;
- }
-
-
- ++cnt;
- }
-
-
- memcpy( &t, &src[idx], sizeof(Elem) );
- memcpy( &src[idx], &src[l], sizeof(Elem) );
- memcpy( &src[l], &t, sizeof(Elem) );
-
- }
-
- }
-
-
-
-
- int PartPartion( Elem * src, int start, int end );
-
-
-
- void PartQuickSort( Elem * src, int start , int end, int k )
- {
-
-
-
-
-
-
-
-
-
-
-
-
-
- int m = 0;
-
-
-
-
- if( start < end )
- {
- m = PartPartion( src, start , end );
-
- if( m <= k )
- PartQuickSort( src, m+1 , end, k - m + 1 );
- else
- PartQuickSort( src, start , m - 1, k );
-
- }
-
- }
-
- int PartPartion( Elem * src, int start, int end )
- {
- Elem t, mid;
-
- int i,j;
-
- i = start;
- j = end;
- mid = src[start];
-
- while( i< j )
- {
- while( i
- j--;
-
- while( i < j && src[i].weight >= mid.weight )
- i++;
-
- if( i
- {
-
- memcpy( &t, &src[i], sizeof(Elem) );
- memcpy( &src[i], &src[j], sizeof(Elem) );
- memcpy( &src[j], &t, sizeof(Elem) );
- }
- }
-
- memcpy( &t, &src[i], sizeof(Elem) );
- memcpy( &src[i], &src[start], sizeof(Elem) );
- memcpy( &src[start], &t, sizeof(Elem) );
- ++cnt;
-
- return i;
- }
-
- void QuickSort( Elem * src, int start , int end )
- {
-
- if( start < end )
- {
- int m = PartPartion( src, start , end );
- QuickSort( src, start, m -1 );
- QuickSort( src, m +1, end );
- }
- }
-
-
-
-
-
- bool AdjHeap( int * WArray, int i, int len );
- void MinHeap( int * WArray, int len );
- void HeapSort( int * WArray, int len );
-
- void HeapK( Elem * src, int k )
- {
-
-
- int * weight = new int[ k ];
- memset( weight, 0, k );
-
- long i;
- int idx = 0;
-
-
- for( i=0; i
- weight[i] = src[i].weight;
-
-
- MinHeap( weight, k );
-
-
-
- for( i=k; i
- {
- if( weight[0] < src[k].weight )
- {
-
-
- weight[0] = src[k].weight;
- AdjHeap( weight, 0, k - 1 );
-
- }
- }
-
-
-
- HeapSort( weight, k );
-
- for( i=0; i
- cout<< weight[i] << " ";
- cout<
-
-
-
- delete weight;
- }
-
- void HeapSort( int * WArray, int len )
- {
- int i;
- int t;
- for( i=0; i
- {
-
- t = WArray[0];
- WArray[0] = WArray[len - i -1];
- WArray[len - i - 1] = t;
-
-
- AdjHeap( WArray, 0, len - i - 2 );
-
- }
- }
-
-
- bool AdjHeap( int * WArray, int i, int len )
- {
- bool change = false;
- int j,t;
- for( j =i*2+1; j <= len; j = j*2+1 )
- {
-
- if( j +1 <= len && WArray[j] > 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;
-
-
-
- int i;
-
-
-
- len--;
- for( i = (len-1)/2; i >=0; i-- )
- AdjHeap( WArray, i, len );
-
- }
-
-
-
-
-
-
-
-
- void Countsort( Elem * src, int k )
- {
- long i,j;
- int max;
- int wt;
- int * kArray = new int[k];
- long take = GetTickCount();
-
- max = src[0].weight;
- for( i=0; i
- {
- wt = src[i].weight;
- max < wt ? max = wt:max;
- }
-
- int * T = new int[ max + 1 ];
- memset( T, 0, sizeof(int)*(max + 1) );
-
- for( i=0; i
- {
- wt = src[i].weight;
- T[ wt ]++;
- }
-
-
- int n = k;
- int idx = 0;
- for( i = max; i>0 ; i-- )
- {
-
- if( !T[i] )
- continue;
- if( T[i] >= n )
- {
-
- for( j =0; j
- {
- kArray[idx++] = i;
-
- }
- break;
- }
- else
- {
-
- for( j =0; j
- {
- kArray[idx++] = i;
-
- }
- n -= T[i];
- }
- }
-
- for( j =0; j
- cout<" ";
- cout<
- cout<<"tick="<< GetTickCount() - take <
- delete T;
- delete kArray;
- }
-
-
- void PrintElem( Elem * src, int Len )
- {
- for( int i =0; i< Len; i++ )
- cout<" ";
- cout<
- }
呵呵,相信在面试时能详细说出以上几钟算法的优缺点,并现场写出一两个,估计他会当场拍板:我找的就是你!
呼~~~当时就是衰在这个上啦, 所以决定完整的做一遍, 基础还是很重要的!!大家也加油啦~~~