八大排序算法-歸併排序

基本思想

歸併(Merge)排序法是將兩個(或兩個以上)有序表合併成一個新的有序表,即把待排序序列分爲若干個子序列,每個子序列是有序的。然後再把有序子序列合併爲整體有序序列。

歸併示例:
這裏寫圖片描述

合併方法

設r[i…n]由兩個有序子表r[i…m]和r[m+1…n]組成,兩個子表長度分別爲m、n-m。

  1. j=m+1;k=i;i=i; //置兩個子表的起始下標及輔助數組的起始下標
  2. 若i>m 或j>n,轉⑷ //其中一個子表已合併完,比較選取結束
  3. //選取r[i]和r[j]較小的存入輔助數組rf

    如果r[i]<r[j],rf[k]=r[i]; i++; k++; 轉⑵
    否則,rf[k]=r[j]; j++; k++; 轉⑵

  4. //將尚未處理完的子表中元素存入rf

    如果i<=m,將r[i…m]存入rf[k…n] //前一子表非空
    如果j<=n , 將r[j…n] 存入rf[k…n]//後一子表非空

  5. 合併結束。

//將r[i…m]和r[m +1 …n]歸併到輔助數組rf[i…n]   
void Merge(ElemType r,ElemType rf,int i,int m, int n){
    int j,k;
    for(j=m+1,k=i;i<=m && j<=n;k++){
        if(r[i]<r[j]){//將比較小的元素插入到rf中元素k和i(或者j)的位置後移 
            rf[k] = r[i++];
        }else{
            rf[k] = r[j++];
        }
    }
    while(i<=m){
        rf[k++] = r[i++]; //如果前半部分有剩餘則補到rf後邊 
    }
    while(j<=n){
        rf[k++] = r[j++];//如果後半部分有剩餘則補到rf後邊 
    }
} 

兩路歸併的遞歸方法

//兩路歸併的遞歸算法
void MSort(ElemType r,ElemType rf,int s,int t){
    ElemType rf2;
    if(s == t){
        rf[s] = r[s];   //當時單個元素的時候結束遞歸,開始歸併 
    }else{
        int m = (s+t)/2;//將r[s...t]平分成兩部分r[s...m]和r[m+1...t]
        MSort(r,rf2,s,m);//遞歸將r[s...m]歸併到rf2[s...m] 
        MSort(r,rf2,m+1,t);//遞歸將r[m+1...t]歸併到rf2[m+1...t] 
        Merge(rf2,rf,s,m,t);//將rf[s...m]和rf[m+1...t] 歸併到rf[s...t] 
    }
} 

完整代碼

#include<stdio.h>

//定義長度爲10的整型數組類型 
typedef int ElemType[10];

//將r[i…m]和r[m +1 …n]歸併到輔助數組rf[i…n]   
void Merge(ElemType r,ElemType rf,int i,int m, int n){
    int j,k;
    for(j=m+1,k=i;i<=m && j<=n;k++){
        if(r[i]<r[j]){//將比較小的元素插入到rf中元素k和i(或者j)的位置後移 
            rf[k] = r[i++];
        }else{
            rf[k] = r[j++];
        }
    }
    while(i<=m){
        rf[k++] = r[i++]; //如果前半部分有剩餘則補到rf後邊 
    }
    while(j<=n){
        rf[k++] = r[j++];//如果後半部分有剩餘則補到rf後邊 
    }
} 
//兩路歸併的遞歸算法
void MSort(ElemType r,ElemType rf,int s,int t){
    ElemType rf2;
    if(s == t){
        rf[s] = r[s];   //當時單個元素的時候結束遞歸,開始歸併 
    }else{
        int m = (s+t)/2;//將r[s...t]平分成兩部分r[s...m]和r[m+1...t]
        MSort(r,rf2,s,m);//遞歸將r[s...m]歸併到rf2[s...m] 
        MSort(r,rf2,m+1,t);//遞歸將r[m+1...t]歸併到rf2[m+1...t] 
        Merge(rf2,rf,s,m,t);//將rf[s...m]和rf[m+1...t] 歸併到rf[s...t] 
    }
} 
//打印 
void print(ElemType r,int n){
    int i;
    for(i=0;i<n;i++){
        printf("%3d",r[i]);
    }
    printf("\n");
}

int main(){
    ElemType r = {3,1,5,7,2,4,9,6,10,8}; 
    ElemType rf; 
    printf("排序前:\n");
    print(r,10); 
    printf("歸併排序後:\n");
    MSort(r,rf,0,9);
    print(rf,10);

    return 0;
} 

執行結果

這裏寫圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章