資料結構與演算法 (六) 歸併排序
阿新 • • 發佈:2018-12-27
1.演算法思想
歸併排序的思想 將已經排序的檔案進行合併 得到完全排序的檔案 合併時只要比較各個子檔案的第一個記錄的排序碼最小的那個記錄就是排序後的第1個記錄 取出這記錄然後繼續比較各子檔案的第1個記錄 便可找出排序後的第二個記錄 如此反覆 對每個檔案經過一趟掃描 便可得到最終的排序結果
2.演算法實現
sort.h
struct forSort { int key[3]; struct forSort *next; }; typedef struct forSort ForSort;
main.c
#include <stdio.h> #include <stdlib.h> #include <string.h> #include "sort.h" void MergeSort(ForSort A[],int n) { int k; ForSort *B =(ForSort * ) malloc(n*sizeof(ForSort)); //初始化子檔案長度為1*/ k=1; while(k<n) { //將A 中的子檔案經過一趟歸併儲存到陣列 B*/ //k 檔案長度 //n 待排序檔案記錄數 OnePassMerge(B,A,k,n); //歸併後文件增加一倍 k<<1; if(k<=n) //已歸併排序完畢 ,單結果在臨時陣列B中呼叫標準函式memcpy()將其複製到A 中。memcpy() 包含在標頭檔案<memory.h> 或者<string.h> 中 memcpy(A,B,n*sizeof(ForSort)); else { //將B 中的子檔案經過一趟歸併儲存到陣列A 中 OnePassMerge(A,B,k,n); //歸併後文件長度增加1倍 k<<=1; } } } //一趟兩組歸併 // 一趟歸併函式 將src中部分排序的多個檔案歸併到Dst中 子檔案的長度為Len */ void OnePassMerge(ForSort Dst[],ForSort Src[],int Len,int n) { int i; for(i=0; i<n-2*Len; i+=2*Len) //執行兩兩歸併 將Src 中長度為Len 的子檔案歸併成長度為2*Len的子檔案,結果存放在Dst 中*/ TwoWayMerge(Dst,Src,i,i+Len-1,i+2*Len-1); if(i<n-Len) //尾部至多還有兩個子檔案 TwoWayMerge(Dst,Src,i,i+Len-1,n-1); else /*尾部可能還有一個子檔案,直接複製到Dst中*/ memcpy(&Dst[i],&Src,(n-i)*sizeof(ForSort)); } /* 兩兩歸併函式,將 Src 中從s到s1 的子檔案和從e1+1 到e2的子檔案進行歸併 結果存放Dst中 從s開始的位置*/ void TwoWayMerge(ForSort Dst[],ForSort Src[],int s,int e1,int e2) { int s1,s2; for(s1=s,s2=e1+1; s1<=e1 && s2<=e2;) if(Src[s1].key<=Src[s2].key) /*第一個子檔案最前面記錄其排序碼小,將其歸併到Dst */ Dst[s++]=Src[s++]; else // 第二個子檔案最前面記錄其排序碼小 將其歸併到Dst Dst[s++]=Src[s2++]; if(s1<=e1) //第一個子檔案未歸併完,將其直接複製到Dst中 memcpy(&Dst[s],&Src[s1],(e1-s1+1)*sizeof(ForSort)); else //從第二個子檔案未歸併完 將其直接複製到Dst中 memcpy(&Dst[s],&Src[s1],(e2-s2+1)*sizeof(ForSort)); } int main() { return 0; }