如何給100億個數字排序?

場景

之前寫過一篇海量數據中統計ip出現次數最多的博客,今天再寫篇類似的,當然會有不同的地方,相同的地方我快速寫過,詳細的可以看之前的博客

今天要給100億個數字排序,100億個 int 型數字放在文件裏面大概有 37.2GB,非常大,內存一次裝不下了。那麼肯定是要拆分成小的文件一個一個來處理,最終在合併成一個排好序的大文件。

實現思路

1.把這個37GB的大文件,用哈希分成1000個小文件,每個小文件平均38MB左右(理想情況),把100億個數字對1000取模,模出來的結果在0到999之間,每個結果對應一個文件,所以我這裏取的哈希函數是 h = x % 1000,哈希函數取得"好",能使衝突減小,結果分佈均勻。

2.拆分完了之後,得到一些幾十MB的小文件,那麼就可以放進內存裏排序了,可以用快速排序,歸併排序,堆排序等等。

3.1000個小文件內部排好序之後,就要把這些內部有序的小文件,合併成一個大的文件,可以用二叉堆來做1000路合併的操作,每個小文件是一路,合併後的大文件仍然有序。

  • 首先遍歷1000個文件,每個文件裏面取第一個數字,組成 (數字, 文件號) 這樣的組合加入到堆裏(假設是從小到大排序,用小頂堆),遍歷完後堆裏有1000個 (數字,文件號) 這樣的元素
  • 然後不斷從堆頂拿元素出來,每拿出一個元素,把它的文件號讀取出來,然後去對應的文件裏,加一個元素進入堆,直到那個文件被讀取完。拿出來的元素當然追加到最終結果的文件裏。
  • 按照上面的操作,直到堆被取空了,此時最終結果文件裏的全部數字就是有序的了。

最後我用c++寫了個實驗程序,具體代碼在這裏可以看到。

思維拓展

類似的100億個數字求和,求中位數,求平均數,套路就是一樣的了。
求和:統計每個小文件的和,返回給master再求和就可以了。
求平均數:上面能求和了,再除以100億就是平均數了
求中位數:在排序的基礎上,遍歷到中間的那個數就是中位數了。



作者:ck2016
原文鏈接:http://www.jianshu.com/p/8dc11152f178
著作權歸作者所有,已獲得作者授權轉載
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章