下面的問題描述及相關文字都參考於csdn中july的部落格,在此對july表示感謝。july的部落格位址如下:
在對海量資料排序時,有時不能把資料全部匯入到記憶體中,這時需要用到多路歸併排序。
比如輸入:乙個最多含有n個不重複的正整數(也就是說可能含有少於n個不重複正整數)的檔案,其中每個數都
小於等於
n,且n=10^7。
輸出:得到按從小到大公升序排列的包含所有輸入的整數的列表。
條件:最多有大約1mb的記憶體空間可用,但磁碟空間足夠。且要求執行時間在5分鐘以下,10秒為最佳結果。
解答:1、記憶體排序
由於要求的可用記憶體為 1mb,那麼每次可以在記憶體中對 250k 的資料進行排序,然後將有序的數寫入硬碟。那麼 10m 的資料需要迴圈 40 次,最終產生 40 個有序的檔案。
2、歸併排序
1. 將每個檔案最開始的數讀入(由於有序,所以為該檔案最小數),存放在乙個大小為40 的 first_data 陣列中;
2. 選擇 first_data 陣列中最小的數 min_data,及其對應的檔案索引 index;
3. 將 first_data 陣列中最小的數寫入檔案 result,然後更新陣列 first_data(根據 index讀取該檔案下乙個數代替 min_data);
4. 判斷是否所有資料都讀取完畢,否則返回 2。
流程圖如下:
自己寫的對19個陣列進行5路歸併的程式,只是簡單實現。
假定5個陣列已經分別排好序了:,,,, 0
511184
79146
8121710
1315161
23剛開始時,從5個陣列中讀入最初的資料到tmp[5]陣列中,即0,4,6,10,1.找出最小的值為0,在第0個陣列中。把0放入最終的接收陣列data中,並把第0個陣列更新,data[0]=0:05
111847
91468
1217
1013
151612
3 此時最小值為1,在第4個陣列中,data[1]=1:05
111847
91468
1217
1013
151612
3 data[2]=205
111847
91468
1217
1013
151612
3 ...
直至全部比較完。
#include #include #include #include #include using namespace std;
const int max=9999;
int main()
;//接收最終的有序陣列
//等待歸併的5個有序子陣列
int a0[4]=;
int a1[4]=;
int a2[4]=;
int a3[4]=;
int a4[3]=;
int len0,len1,len2,len3,len4;
len0=len1=len2=len3=4;
len4=3;
int i[5]=;//指標陣列,i[0]指向第乙個陣列,i[1]指向第二個陣列.....
int k=0;
int tmp[5]=;
while(i[0]tmp[j])
}i[pos]++;//指標往後移動乙個
data[k++]=min;//記錄
} for(int i=0;i
多路歸併排序
我們有如下乙個問題 對於若干個長度相同的序列,將其合併成乙個有序的序列。暴力的方法顯然是不可取的,這裡可以利用優先佇列來處理這個問題。首先從簡單的開始,對於2路歸併排序,設兩個序列為,將,排序,有 a1 a2 a3 an b1 b2 b3 bn 建立乙個優先佇列,佇列中首先存入元素 a1,0 b1,...
多路歸併排序
雪壓枝頭低,雖低不著泥 今天準備放假,無聊看到乙個場景題,問題如下 有乙個檔案裡面儲存著很多很多很多的無序的數,然後要求進行乙個排序,記憶體限定,磁碟足夠 然後搗鼓了一下,學到了一種新技能 多路歸併排序 學習的過程是這樣的 第一步 把儲存著很多很多很多數的檔案進行切割,切割成n個小檔案,每個小檔案都...
多路歸併排序的實現
為了更好地測試程式,首先利用以下方法生成了1000000個整數,每個整數均不相同 生成隨機排列的1000000個數字,每個數字都不相同 const int size 1000000 int num size void produce srand unsigned time null 隨機交換隨機的兩...