海量數據查找中位數


現在 有10億個int型的數字(JAVA中 int 型占4B),以及一台可用內存為1GB的機器,如何找出這10億個數字的中位數?

 

中位數定義:數字排序之后,位於中間的那個數。比如將10億個數字進行排序(位置從1到10億),排序之后,位於第5億個位置的那個數 就是中位數。

關於中位數,可參考:快速排序中的分割算法的解析與應用

 

一種方法是定義一個長度為10億的整型數組,采用排序算法排序。但是:

10億個數字,每個數字在內存中占4B,10億個數字完全加載到內存中需要:10*108*4B ,約為:4GB內存。顯然不能把所有的數字都裝入內存。

 

這里,采用基於二進制位比較 和 快速排序算法中的“分割思想”來尋找中位數。具體如下:

假設10億個數字保存在一個大文件中,依次讀一部分文件到內存(不超過內存的限制:1GB),將每個數字用二進制表示,比較二進制的最高位(第32位),如果數字的最高位為0,則將這個數字寫入 file_0文件中;如果最高位為 1,則將該數字寫入file_1文件中。【這里的最高位類似於快速排序中的樞軸元素】

從而將10億個數字分成了兩個文件(幾乎是二分的),假設 file_0文件中有 6億 個數字,file_1文件中有 4億 個數字。那么中位數就在 file_0 文件中,並且是 file_0 文件中所有數字排序之后的第 1億 個數字。

【為什么呢?因為10億個數字的中位數是10億個數排序之后的第5億個數。現在file_0有6億個數,file_1有4億個數,file_0中的數都比file_1中的數要大(最高位為符號位,file_1中的數都是負數,file_0中的數都是正數,也即這里一共只有4億個負數,排序之后的第5億個數一定是正數,那么排序之后的第5億個數一定位於file_0中)】。除去4億個負數,中位數就是6億個正數從小到大排序之后 的第 1 億個數

現在,我們只需要處理 file_0 文件了(不需要再考慮file_1文件)。對於 file_0 文件,同樣采取上面的措施處理:將file_0文件依次讀一部分到內存(不超內存限制:1GB),將每個數字用二進制表示,比較二進制的高位(第31位),如果數字的次高位為0,寫入file_0_0文件中;如果次高位為1,寫入file_0_1文件 中。

現假設 file_0_0文件中有3億個數字,file_0_1中也有3億個數字,則中位數就是:file_0_0文件中的數字從小到大排序之后的第1億個數字。

拋棄file_0_1文件,繼續對 file_0_0文件 根據 次次高位(第30位) 划分,假設此次划分的兩個文件為:file_0_0_0中有0.5億個數字,file_0_0_1中有2.5億個數字,那么中位數就是 file_0_0_1文件中的所有數字排序之后的 第 0.5億 個數。

......

按照上述思路,直到划分的文件可直接加載進內存時(比如划分的文件中只有5KW個數字了),就可以直接對數字進行快速排序,找出中位數了。當然,你也使用“快排的分割算法”來找出中位數(比使用快速排序要快)

 

總結:上面的海量數據尋找中位數,其實就是利用了“分割”思想,每次將 問題空間 大約分解成原問題空間的一半左右。(划分成兩個文件,直接丟棄其中一個文件),故總的復雜度可視為O(logN) N=10億。

 

參考資料:

快速排序中的分割算法的解析與應用

五種常用的算法設計技巧之二:分治算法

海量數據處理之BitMap

 

原文:http://www.cnblogs.com/hapjin/p/5769087.html


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM