怎樣對千萬級甚至億級數據量排序

編程珠璣第二版第一章就有相似的問題,問題描述以下:算法

有最多1000萬條不一樣的整型數據存在於硬盤的文件中(數據不超過最大值),如何在1M內存的狀況下對其進行儘量快的排序。編程

數據特徵:單個數據<=1000萬、不一樣的(沒有重複)、整型(int,4B)

要求:1M內存、儘量快

分析:1MB = 1*1024*1024 B   能存儲大於25萬個int類型的整數。因此每次咱們能夠排序25萬條記錄,一共排序40次。

 

(1)一個簡單的思路是讀1000萬條1次,對第i個25萬條數據進行排序,並將排好的結果存成外部文件i(這裏能夠用常見的內部排序,如快排),最後咱們生成了40個排好序的外部文件,而後對這40個文件進行歸併排序輸出成1個文件。數據結構

 

(2)更好的思路是位向量排序,咱們能夠申請一個1千萬長度的位向量bit[10000000],全部位設置爲0,順序讀取待排序文件,每讀入一個數i,便將bit[i]置爲1。當全部數據讀入完成,便對 bit作從頭至尾的遍歷,若是bit[i]=1,則輸出i到文件,當遍歷完成,文件則已排好序。spa

這個思路和桶排序同樣,算法的關鍵是位向量。對於不支持bit數據結構的語言咱們能夠本身實現位操做,int是32位的,因此咱們須要[1千萬/32+1]個int類型存儲,大約1.2M。(雖然差點不符合題目的要求,可是不失爲一種更好的解題思路)。code

將第i位置爲1的時候能夠用以下操做:對象

a[i/32] | (1 << (i%32)); 

第i位確定在i/32個int上,i%32是偏移量,而後經過按位或來將特定位置1。(不明白的能夠了解一下位計算)blog

爲了計算速度更快,上述公式能夠徹底由位運算替代:排序

a[i >>5] |= (1 << (i & 31));

 

總結內存

對於大的數量級的排序,基本思路是分而治之的思想,位向量方法雖然效率很高,可是要注意一些限制條件(數據不能重複、不適合稀疏的數據分佈等)。hash

編程珠璣中的例子是int型的數據排序,實際咱們面臨的問題可能不會這麼簡單,例如須要對複雜數據類型進行排序(對象),咱們可讓對象實現compareTo,重寫hashcode、equals等等。

相關文章
相關標籤/搜索