海量数据找中位数

法一

原博客链接

思路如下:

从10亿个数据(int型占据4B)中找中位数,内存限制为1GB。

不可能一次性把数据全部加载到内存中,再使用快速排序算法,因为10亿*4B大约为4GB,内存不够。

可以一次性读入1GB的数据(分10次读取),然后对读入的1GB数据按照最高位即第32位的值进行分类并写入文件,如果最高位是1,写入file1,否则写入file2。那么file1全是负数,file2全是正数,如果file1中有4亿个数字,file2中有6亿个数字,那么中位数就是file2中排序之后从小到大的第1亿个数。

然后再把file2中的数据每次读入1GB进入内存,然后对读入的数据按照次高位即第31位的值进行分类写入文件,如果最高位是1,写入file3,否则写入file4,那么file3中的数据都比file4中的数据大,如果file3中有3亿个数字,file4中也有3亿个数字,那么中位数就是file4中从小到大排序后的第1亿个数字。

然后再把file4中的数据每次都读入1GB进入内存,然后对读入的数据按照次次高位即第30位的值进行分类写入文件。。。

如此下去,直至判断中位数为某一个文件中,且该文件中数据个数在2.5亿个(或者更少)时即可用快速排序找出它。

 

法二

原博客链接

思路如下:

从10亿个数据(int型占据4B)中找中位数,内存限制为2GB。

1 读一遍10亿个整数,把整数映射进256M个区间中,每个区间有一个64位的无符号整数记录值位于该区间的元素个数。

8B*256M=2GB,每个区间的值区间是2^32/2^28(256M)=16,即第一个区间统计值在0-15范围的整数个数,第二个区间统计值在16-31范围的整数个数。。。

2 从前往后对每一区段的个数累加,当这个值超过5亿时,记录下这个超过5亿的区段,即它的值的范围,记为[a,a+15];比如如果加到这一段时,刚好是5亿零5,那么需要找出[a,a+15]区间的第5小的数。我们需要记录这一区段前的区段和m。然后释放内存。

3 再次遍历10亿个整数,对[a,a+15]值范围的整数计数,共有16个计数,

4 对新的计数依次与m进行累加,如果超过5亿就停止,该计数所对应的数值即第5亿个数字。

 

改进:

(1)如果是32位有符号整数,可以改变映射区间,有负有正。

(2)如果是64位,可以增大区间范围

(3)如果某区间的计数过大,发生溢出,就认为该整数即为所求或需做相应的处理。

 

你可能感兴趣的:(海量数据)