歸併排序--自上而下和自下而上兩種方法的實現
阿新 • • 發佈:2019-02-11
歸併排序思想
自上而下的遞迴
對一個數組(str)選中一箇中間位置(mid=(start+end)/2),分別進行左遞迴(mergeSort(str,start,mid,length)),右遞迴(mergeSort(str,mid+1,end,length)),在回朔的時候分別對以中間為分割的陣列進行排序(merge(str,start,end,mid)),此時是一個歸併的過程,這是自上而下的方法。
自下而上的遞迴
自下而上歸併其實就是自上而下的時候的回朔過程,先對每一個數字排序,在兩兩排序,在對結果兩兩排序,直到完成。
具體程式碼實現(自上而下)
int merge(long *str,int start,int end,int mid){ long *tmp = (long *)malloc(sizeof(long)*(end-start+1)); int i=start; int j=mid+1; int k=0; while(i<=mid && j<=end){ if(str[i]<str[j]) tmp[k++]=str[i++]; else tmp[k++]=str[j++]; } while(i<=mid) tmp[k++] = str[i++]; while(j<=end) tmp[k++] = str[j++]; for(i=start;i<=end;i++) str[i]=tmp[i-start]; free(tmp); } int mergeSort(long *str,int start ,int end,int length){ if(str == NULL || start <0 || end >length || length <=0 || end <= start) return ; int mid = (start + end )/2; mergeSort(str,start,mid,length); mergeSort(str,mid+1,end,length); merge(str,start,end,mid); } void call(){ long *array = (long *)malloc(sizeof(long)*10); genrand(10,array); mergeSort(array,0,9,10); int i=0; for(i;i<10;i++) printf("%ld\n",array[i]); }
自下而上程式碼實現
void merge(long *str,int start ,int end,int mid){ if(start>=end || mid >=end) return; int i =start; int j =mid+1; int k =0; long *tmp = (long *)malloc(sizeof(long)*(end-start+1)); while(i<=mid && j<=end){ if(str[i]<=str[j]) tmp[k++]=str[i++]; else tmp[k++]=str[j++]; } while(i<=mid) tmp[k++]=str[i++]; while(j<=end) tmp[k++]=str[j++]; for(i=start;i<=end;i++) str[i]=tmp[i-start]; free(tmp); } void mergeGroup(long *str,int len,int gap){ int i=0; //需要歸併的總長度 int twoLen = 2*gap; //因為陣列下標以0開始,所以要-1 for(i=0;i+twoLen-1<len;i+=twoLen){ //i是起點,起點+總長度-1 為終點,起點+每一個數組的長度-1為分割點 merge(str,i,i+twoLen-1,i+gap-1); } //如果便利一遍後 分割點還是小於陣列最後一個下標,則表示還有最後一個歸併沒有完成,起點為i終點為len-1 if(i+gap-1 < len-1) merge(str,i,len-1,i+gap-1); } void mergeSortDownUp(long * str,int length){ int n; if(str == NULL || length<=0) return; //n 可以理解為每一次歸併的陣列長度 for(n=1;n<length;n*=2) mergeGroup(str,length,n); } void call(){ long *array = (long *)malloc(sizeof(long)*10); genrand(10,array); mergeSortDownUp(array,10); int i=0; for(i;i<10;i++) printf("%ld\n",array[i]); }
genrand() 和swap()函式的實現如下。
int genrand(int num,long * array ){
if (num>10000)
return 0 ;
srand((unsigned int)time(0));
int i=0;
for(i=0;i<num;i++)
array[i] = rand();
return 1;
}
void swap(long *A,long *B){
long tmp;
tmp = *A;
*A = *B;
*B = tmp;
}
執行環境:ubuntu14.04 、gcc
注:如有錯誤望批評指正。