大数据中位数怎么运算_转:海量数据找中位数

题目如下:

只有2G内存的pc机,在一个存有10G个整数的文件,从中找到中位数,写一个算法。

算法:

1.利用外排序的方法,进行排序 ,然后再去找中位数

2.另外还有个思路利用堆

先求第1G大,然后利用该元素求第2G大,然后利用第2G大,求第3G大...当然这样的话虽不需排序,但是磁盘操作会比较多,具体还需要分析下与外排序的效率哪个的磁盘IO会比较多

建立一个1g个整数的最大值堆,如果元素小于最大值则入堆,这样可以得到第1g大的那个元素然后利用这个元素,重新建一次堆,这次入堆的条件还要加上大于这个第1g大的元素,这样建完堆可以得到第2g大的那个 ...

3.借鉴基数排序思想

偶认为可以用位来判断计数,从最高位到最低位,为了方便表述我们假设为无符号整数,即0x00000000~0xFFFFFFFF依次递增,那么可以遍历所有数据,并记录最高位为0和1的个数(最高位为0的肯定是小于最高位为1的)记为N0、N1

那么根据N0和N1的大小就可以知道中位数的最高位是0还是1

假设N0>N1,那么再计算N00和N01,

如果N00>(N01+N1),则说明中位数的最高两位是00

再计算N000和N001.。。。依次计算就能找到中位数

如果改进一下,设定多个计数器

好像一次磁盘io也可以统计出N0,N00,....的数值

4.借鉴桶排序思想

一个整数假设是32位无符号数

第一次扫描把0~2^32-1分成2^16个区间,记录每个区间的整数数目

找出中位数具体所在区间65536*i~65536*(i+1)-1

第二次扫描则可找出具体中位数数值

第一次扫描已经找出中位数具体所在区间65536*i~65536*(i+1)-1

然后第二次扫描再统计在该区间内每个数出现的次数,就可以了.

题目:在一个文件中有 10G 个整数,乱序排列,要求找出中位数。内存限制为 2G。只写出思路即可(内存限制为 2G的意思就是,可以使用2G的空间来运行程序,而不考虑这台机器上的其他软件的占用内存)。分析:既然要找中位数,很简单就是排序的想法。那么基于字节的桶排序是一个可行的方法 :

思想:将整形的每1byte作为一个关键字,也就是说一个整形可以拆成4个keys,而且最高位的keys越大,整数越大。如果高位keys相同,则比较次高位的keys。整个比较过程类似于字符串的字典序。

第一步:把10G整数每2G读入一次内存,然后一次遍历这536,870,912个数据。每个数据用位运算">>"取出最高8位(31-24)。这8bits(0-255)最多表示255个桶,那么可以根据8bit的值来确定丢入第几个桶。最后把每个桶写入一个磁盘文件中,同时在内存中统计每个桶内数据的数量,自然这个数量只需要255个整形空间即可。

代价:(1) 10G数据依次读入内存的IO代价(这个是无法避免的,CPU不能直接在磁盘上运算)。(2)在内存中遍历536,870,912个数据,这是一个O(n)的线性时间复杂度。(3)把255个桶写会到255个磁盘文件空间中

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值