利用有限空间对一个大文件中的数字进行排序

问题

有一个10G大小的文件中的数字排序
32位无符号整数的范围是0~4294967295,有一个10G大小的文件,每一行都装着这种类型的数字,整个文件是无序的。给你5G的内存空间,要求请你输出一个10G大小的文件,其中存储了原文件所有数字排序的结果。

本题当然不能用一般的排序算法直接排序,因为一般的归并排序、快速排序等都需要所有的数据全都读到内存中。而本题有10G的数据,5G的内存显然放不下。

解决方法:利用堆。核心思路即利用堆求top K的算法。

1

准备一个用于保存较大值的小根堆,这个小根堆容量有限制(用一个变量记录,如本题根据5GB限制,假设容量限制为size)。再准备一个保存小根堆里词频的map,key是num,value是出现次数。map和小根堆是对应的,任意时刻map中的key和小根堆中的数一定一模一样。

2

遍历这10G的大小文件的数字,依次考虑是否放入小根堆中。在加入小根堆前,先用map查一下该数是否在小根堆中(map中是否有此key)。

2.1

若在,则直接设置该key的value++,就不执行加入小根堆操作了。

2.2

如果不在,那么就要考虑是否加入小根堆:

2.2.1
当堆的大小小于容量限制size时,一个数字直接进小根堆,同时在map中创建好一条key-value记录(该记录初始value为1)。

2.2.2
当堆的大小已经达到容量限制size后,则将当前该数与堆顶的数比较。①若当前的数小于堆顶的数,则不加入小根堆,跳过此数。②若当前的数大于堆顶的数,则弹出堆顶的数,将map中原堆顶数的key-value记录删除,然后将当前的数加入小根堆,同时在map中创建好一条key-value记录(该记录初始value为1)。③不可能出现当前的数等于堆顶的数的情况,因为该情况在情况2.1中。

3

最后,弹出小根堆中所有的数,此时是从小到大排列的最大的size个数(写出到一个文件中)。同时记录好本次弹出的最小数,下次再次遍历,此轮遍历只遍历小于刚才弹出最小数的数,那么遍历完成后就又能获得次大的size个数。如此进行下去,最后一定能让所有数字的排好序。

总结

注意,在上述流程中,小根堆实际上用来存储每轮最大的size个数的!之所以用小根堆,是因为堆顶代表了本轮最大的size个数中的最小那个数,新的数只要比他大,就会顶掉它,加入本轮最大的size个数的队伍中。这就是利用堆求top K(本例中是求top size)的核心思想!

整个过程中,5G内存需要分配给两个结构,即等占空间的一个map和小根堆。如果想多用内存,那么小根堆的容量限制就设大点,那么就有可能能少遍历几次就排好序。

根据以上的叙述应该是可以直接写出代码的。楼主太懒了,就没写了。感兴趣的朋友可以自己写一下😉。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值