大數外部排序

2021-09-03 01:34:04 字數 4122 閱讀 5762

題意:將百萬級資料排序,已知記憶體最大處理4k資料

4k記憶體容量是4000位元組,也就是說能處理1000個數假如說現在有n資料進行排序,n為百萬級,而記憶體一次只能處理1000個資料,我們做法是分部做,即先把n分成n/1000份資料,這樣每份資料就都能用內部排序方法實現(本題使用2路),每份資料存在乙個檔案裡然後再把這些檔案合併。

具體實現過稱為:假設原檔案儲存在test.txt中分別從總資料test中fscanf讀取1000個資料,每個檔案依次命名1,2,3……理論是n/1000個,即filenum個檔案(最後乙個檔案資料個數不一定為1000),每個檔案中資料使用二路歸併排序sortfile排好,接下來就是對filenum組資料進行排序,即呼叫mergefile函式歸併,一般來說這一步使用多路歸併、敗者樹方法,當然也可以二路歸併本題採用」二路歸併「:使用非遞迴,兩兩合併(個數為奇數最後乙個不用歸),使用file_tag標記進行到第幾組了,file_tag==filenum那麼第一次迴圈歸併就結束了,get_filenum記錄得到的歸併檔案數,之前的檔案使用remove刪去,每次迴圈檔案總數總要用新得到的歸併檔案總數代替filenum=get_filenum,直到檔案數filenum為1那麼就完成了

純c**:

#include#include#include#include#define maxnum 2000

///全域性變數

int filenum;///當前檔案數

int file_tag;///標記歸併到哪個檔案了

int get_filenum;///記錄歸併得到的檔案數

///函式宣告

void creatfile();//用於獲取100萬個隨機數

void sortfile();//將100萬個隨機數拆分為filenum個檔案,每拆分好乙個便內部排序,呼叫了函式creatdatafile、merge_sort

void creatdatafile(int data, int count);//將data陣列中排好的資料寫入到檔案中

void merge_sort(int num, int start, int end);//二路歸併排序函式

void merge(int num, int start, int mid, int end);//兩個有序陣列的合併,與上乙個函式構成完整二路歸併排序函式

void mergefile();//對於已經排好序的filenum個檔案採取兩兩合併

int main()

void creatfile()//用於獲取100萬個隨機數

fclose(f);

}void sortfile()//將100萬個隨機數拆分為filenum個檔案,每拆分好乙個便內部排序,呼叫了函式creatdatafile、merge_sort

}if (count != 0)

fclose(f);

free(data);

}///將data中排好的資料寫入到檔案中1,2,3,4

void creatdatafile(int data, int count)

; filename[0] = filenum + '0';

strcat(filename, ".txt");

f = fopen(filename, "w+");

for (int i = 0; i < count; ++i)

fclose(f);

}///二路歸併排序

void merge_sort(int num, int start, int end)

}void merge(int num, int start, int mid, int end)

///file_tag標記進行到第幾組

///get_filenum歸併得到的檔案數目

void mergefile()

; file_tag++;

filename1[0] = file_tag + '0';

strcat(filename1, ".txt");

f1 = fopen(filename1, "r");

///get_filenum++;

char filename[10] = ;

filename[0] = get_filenum + '0';

strcat(filename, "data.txt");

f = fopen(filename, "w+");

int num1;

while (fscanf(f1, "%d", &num1) != eof)

fclose(f1);

fclose(f);

}else

;file_tag++;

filename1[0] = file_tag + '0';

strcat(filename1, ".txt");

f1 = fopen(filename1, "r");

char filename2[10] = ;

file_tag++;

filename2[0] = file_tag + '0';

strcat(filename2, ".txt");

f2 = fopen(filename2, "r");

get_filenum++;

char filename[10] = ;

filename[0] = get_filenum + '0';

strcat(filename, "data.txt");

f = fopen(filename, "w+");

int data;

int count = 0;

int num1, num2;

fscanf(f1, "%d", &num1);

fscanf(f2, "%d", &num2);

while (1)

break;}}

else

break;}}

}fclose(f1);

fclose(f2);

fclose(f);

}char filename1[10] = ;

char filename2[10] = ;

filename1[0] = get_filenum + '0';

filename2[0] = get_filenum + '0';

strcat(filename1, "data.txt");

strcat(filename2, ".txt");

char filename3[10] = ;

char filename4[10] = ;

//假如說歸併得到第3個檔案,那麼產生它的對應的檔案為5,6兩個

filename3[0] = get_filenum * 2 - 1 + '0';

filename4[0] = get_filenum * 2 + '0';

strcat(filename3, ".txt");

strcat(filename4, ".txt");

int r1 = remove(filename3);

int r2 = remove(filename4);

printf("r1=%d r2=%d\n", r1, r2);

// int rename ( const char * oldname, const char * newname )

rename(filename1, filename2);

//printf("filenum=%d file_tag=%d get_filenum=%d\n", filenum, file_tag, get_filenum);

if (file_tag == filenum&&filenum != 1)}}

char filename1[20] = ;

char filename2[20] = ;

filename1[0] = 1 + '0';

strcat(filename1, ".txt");

strcat(filename2, "test_sort.txt");

rename(filename1, filename2);

printf("排序完成,有序序列儲存在:test_sort.txt檔案中\n");

}

排序之外部排序

有時,待排序的檔案很大,計算機記憶體不能容納整個檔案,這時候對檔案就不能使用內部排序了 這裡做一下說明,其實所有的排序都是在記憶體中做的,這裡說的內部排序是指待排序的內容在記憶體中就可以完成,而外部排序是指待排序的內容不能在記憶體中一下子完成,它需要做內外存的內容交換 外部排序常採用的排序方法也是歸...

排序之外部排序

有時,待排序的檔案很大,計算機記憶體不能容納整個檔案,這時候對檔案就不能使用內部排序了 這裡做一下說明,其實所有的排序都是在記憶體中做的,這裡說的內部排序是指待排序的內容在記憶體中就可以完成,而外部排序是指待排序的內容不能在記憶體中一下子完成,它需要做內外存的內容交換 外部排序常採用的排序方法也是歸...

排序(二 外部排序

一 定義 外部排序指的是大檔案的排序,即待排序的記錄儲存在外儲存器上,待排序的檔案無法一次裝入記憶體,需要在記憶體和外部儲存器之間進行多次資料交換,以達到排序整個檔案的目的。二 處理過程 1 按可用記憶體的大小,把外存上含有n個記錄的檔案分成若干個長度為l的子檔案,把這些子檔案依次讀入記憶體,並利用...