求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
直接贴代码吧,废话少讲(先说方法吧)~~~~解释在注释里:)
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
相关文章推荐
- 求N个数中最大的K个数的几种方法与实现
- 求N个数中最大的K个数的几种方法与实现
- 求N个数中最大的K个数的几种方法与实现
- 几种任务调度的java实现方法比较
- 用Delphi实现文件下载的几种方法
- 用Delphi实现文件下载的几种方法
- (c/c++)实现逆序输出整数的几种方法
- 微信小程序实现传参数的几种方法示例
- 几种任务调度的 Java 实现方法与比较
- 实现浏览器全屏窗口的几种方法
- JAVA单例模式的几种实现方法
- Java实现几种常见排序方法(上)
- PHP页面跳转几种实现方法
- WordPress用代码实现相关文章(关联文章)的几种方法
- strlen函数实现的几种方法
- Shell中实现整数自增的几种方法示例
- js实现继承的几种方法
- 在PB中用Enter键实现跳转的几种方法
- java实现同步map的几种方法(lock,synchronized,rwlock,ConcurrentHashMap,hashtable,SynchronizedMap)