基本要點:外部排序顧名思義是對外部儲存空間中資料的排序,那為什麼不能像選擇排序、插入排序、快速排序那樣也直接進行排序呢?原因是外部儲存的資料量可能是非常大的,而計算機的記憶體大小要遠遠小於外存,計算機一下子讀不了那麼多資料,無法一次性對它們進行排序,這就是外部排序產生的原因。
基本思想:
我們這裡借助歸併排序的思想(這也是外部排序中最基本的思想,假設大家已經對歸併排序有一定了解),假設我的乙個檔案中有10000個資料,而我的記憶體每次只能讀2000個資料,那我先對檔案預處理一下,將原檔案切割成5個小檔案,每個檔案中有2000個有序資料(在讀入記憶體2000個資料後,對資料排序後再寫入到新檔案中)。
然後我們開始進行檔案合併(這裡採用2-路歸併)。先分別開啟兩個檔案,分別讀取檔案的第一行資料,把資料較小的寫入到乙個新檔案中,然後把資料較小的檔案再往下讀一行,直到兩個檔案中的資料全部有序地寫到新檔案中為止,這樣原先5個2000個資料的檔案變為2個4000個資料和1個2000個資料的檔案。
重複步驟2,再次合併變為1個8000個資料和1個2000個資料的檔案,再次合併變為1個10000個資料的檔案。排序完成,原先有10000個資料的檔案變得有序。
下面是模擬外部排序的**:
#include
#include
#include
#include
#define maxnum 2000
int filenum;
int filenumtemp;
int filenumend;
void creatfile()
fclose(f);
}void merge(int num, int start, int mid, int end)
void merge_sort(int num, int start, int end)
}void mergefile()
; filenumtemp++;
filename1[0] = filenumtemp + 48;
strcat(filename1, ".txt");
f1 = fopen(filename1, "r");
filenumend++;
char filename[10] = ;
filename[0] = filenumend + 48;
strcat(filename, "temp.txt");
f = fopen(filename, "w+");
int num1;
while (fscanf(f1, "%d", &num1) != eof)
fclose(f1);
fclose(f);
}else
;filenumtemp++;
filename1[0] = filenumtemp + 48;
strcat(filename1, ".txt");
f1 = fopen(filename1, "r");
char filename2[10] = ;
filenumtemp++;
filename2[0] = filenumtemp + 48;
strcat(filename2, ".txt");
f2 = fopen(filename2, "r");
filenumend++;
char filename[10] = ;
filename[0] = filenumend + 48;
strcat(filename, "temp.txt");
f = fopen(filename, "w+");
int temp;
int count = 0;
int num1, num2;
fscanf(f1, "%d", &num1);
fscanf(f2, "%d", &num2);
while (true)
break;}}
else
break;}}
}fclose(f1);
fclose(f2);
fclose(f);
}char filename1[10] = ;
char filename2[10] = ;
filename1[0] = filenumend + 48;
filename2[0] = filenumend + 48;
strcat(filename1, "temp.txt");
strcat(filename2, ".txt");
char filename3[10] = ;
char filename4[10] = ;
filename3[0] = filenumend * 2 - 1 + 48;
filename4[0] = filenumend * 2 + 48;
strcat(filename3, ".txt");
strcat(filename4, ".txt");
int r1 = remove(filename3);
int r2 = remove(filename4);
printf("r1=%d r2=%d\n", r1, r2);
rename(filename1, filename2);
//printf("filenum=%d filenumtemp=%d filenumend=%d\n", filenum, filenumtemp, filenumend);
if (filenumtemp == filenum&&filenum != 1)}}
char filename1[20] = ;
char filename2[20] = ;
filename1[0] = 1 + 48;
strcat(filename1, ".txt");
strcat(filename2, "test_sort.txt");
rename(filename1, filename2);
printf("排序完成,有序序列儲存在:test_sort.txt檔案中\n");
}void creattempfile(int temp, int count)
; filename[0] = filenum + 48;
strcat(filename, ".txt");
f = fopen(filename, "w+");
for (int i = 0; i < count; ++i)
fclose(f);
}void sortfile()
}if (count != 0)
fclose(f);
free(temp);
}int main()
注:使用敗者樹進行多路合併可加快檔案的排序速度,這裡只使用了2-路歸併排序,對原檔案的預處理排序可使用內部排序的任何一種演算法,當然效率越快,排序穩定最好。 外部排序 歸併排序
歸併排序 歸併排序是採用分治的思想,將陣列劃分為兩個子陣列,然後遞迴的將每個子陣列再進行劃分,直到陣列中只剩一下乙個元素,然後開始排序合併,直到將所有的子陣列合併完成,整個資料就是有序的了。歸併排序乙個重要的操作函式就是合併函式 時間複雜度 將陣列分成的子陣列 用二叉樹表示,假設共有n層,第k層共有...
歸併排序 外部排序
基本思想 先對資料進行均分 左右兩半部分 均分到左右部分已經有序 歸併 歸併排序核心步驟 分組 歸併 外部排序 void mergesortnor int array,int size void print int array,int size endif mergesort h mergesort...
歸併排序演算法實現
const int maxn 100 將陣列a的 l1,r1 與 l2,r2 區間合併為有序區間 此處l2即為r1 1 void merge int a,int l1,int r1,int l2,int r2 while i r1 temp index a i 將 l1,r1 剩餘元素加入temp ...