大数据排序问题

问题1:从100亿个数据中找出前100个数据

分析:由于只要找出前100个数据,可以采用堆来进行处理。堆特别适合的场景是从海量数据中找出前m个最大值或最小值,当m不大的时候效率很高。

步骤:

1.读取前100个数据,建立最小堆(最小堆的作用是方便找出目前最大的100个数据中的最小值,把待比较的数据与这个最小值比较就好。由于一次性只读取100个数据,不需要一次性读完所有数据,降低对内存的要求)

2.对余下数据依次进行读取,分别与堆中最小数据进行比较。若当前数据小于堆中最小数据,说明当前数据在前100个以外,即舍弃。若当前数据大于堆中最小数据,则从堆中pop出最小数据,向堆中插入当前数据,并调整堆。

3.最后剩下的100个堆中元素即为所求。


问题2:从100亿个数据中找出前1亿个数据

分析:这个问题和上个问题有所不同。假如还用最小堆法,那么维护一个一亿数据量的堆是非常不高效的,而且堆的空间会很大,占用非常多的内存。可以考虑一下几种方法。


1.位图法(假如每个数据最多重复一次)

首先对内存占用进行分析,假如说每个数据不大于100亿, 而且最多重复一次,那么我们一共需要100亿位。
1byte = 8bit(位)
1024byte = 8*1024 = 1k
1M = 1024k = 8*1024*1024 = 8388608bit
那么100亿位就是100*10^8/8388608 = 1187M,大约需要1G多的空间。

2.快排中的partition方法
因为是寻找前k大个数,只要找到分割整个数据的第k个数据就好。
//快速排序的划分函数
int partition(int v[], int left, int right)
{
	int pivotpos = left, pivot = v[left];
	for(int i=left+1;i<=right;++i)
		if (v[i] < pivot)
		{
			++pivotpos;
			if (pivotpos != i)
				swap(v[i], v[pivotpos]);
		}
	v[left] = v[pivotpos];
	v[pivotpos] = pivot;
	return pivotpos;
}


//线性寻找第k大的数
int select(int v[], int left, int right, int k)
{
	if (left > right || k < 0 ) return -1;
	int pivotpos = partition(v, left, right);
	if (pivotpos > k) 
		return select(v, left, pivotpos - 1, k);
	else if (pivotpos < k) 
		return select(v, pivotpos + 1, right, k);
	else
		return k;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值