題意:將百萬級資料排序,已知記憶體最大處理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的子檔案,把這些子檔案依次讀入記憶體,並利用...