上亿个数据保存在硬盘中,找出最大的N个。

(1)先选N个元素组成一个小根堆,然后遍历剩下的数据,如果第i个元素M大于小根堆的根结点,就删除这个根结点,并将元素M插入这个小根椎,最后,小根堆中的元素就是最大的N个元素。

(2)只要开辟一个稍微大一点的缓冲区存放大于某选定值的数据即可,当缓冲满时,刷新选定值为缓冲区的第n大值,即可(同时清理缓存区)。

(3)用O(M)的时间找出第N大元素,然后再遍历一边找出比这个数大的N个数即可,理论复杂度O(M),不过N较小的时候可能是1L的更有效率

解法(1)及时考虑数据不可能全部加入内存,也可以在内存中开辟一个缓冲区,每次读取磁盘中的K(K<M)个数据进入内存,然后在一个一个的与堆进行比较。当缓冲区空时,则再读入K个数据。总之减少IO读取次数也是一个高效的重要方面。

解法(2)如何选定值

解法(3)是一个方向,可以使用快速排序算法,选择递归搜索的方向,理论上可以达到O(M),但找第N大元素时,如何不需要把所有数据读入内存呢?

给出方法(1)的一个算法,使用set,有重复数据也可以用multiset,set使用的是红黑树,可以改善插入、删除的效率

int main(int argc, char* argv[])
{
	set<int> set_MAX_N;
	ifstream inFile("test.txt");
	int nTemp;
	while(inFile >>nTemp)
	{
		set_MAX_N.insert(nTemp);
		if(set_MAX_N.size() > N)
		{
			set_MAX_N.erase(set_MAX_N.begin());
		}
	}
	for(set<int>::iterator it = set_MAX_N.begin();it != set_MAX_N.end(); it ++)
		cout<< *it <<endl;
	while(1);
	return 0;
}

 


转自:http://bbs.csdn.net/topics/340000263

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值