归并排序

Merge Sort
思路
. 将2个或多个有序的序列合并称为1个有序序列
. 先拆再合:将原始无序记录看作n个无序序列;依次两两合并;直到最后合并称为一个有序序列
. 归并时,每次都比较 头部|第1个 记录
. 采用了分治 - Divide & Conquer和递归 - Recursion的思想
. 更多信息,请查看哔哩哔哩-归并排序Merge Sort
已知待排序关键字为{49, 38, 65, 97, 76, 13, 27},给出2-路合并过程
49 38 65 97 76 13 27
[49] [38] [65] [97] [76] [13] [27]
[38, 49] [65, 97] [13, 76] [27]
[38, 49, 65, 97] [13, 27, 76]
[13, 27, 38, 49, 65, 76, 97]
其中,[38,49]和[65,97]的归并过程为:
. 38和65比较,38小,取出38,余[49]和[65,97]
. 49和比65,49小,取出49,放在38后面,余[65,97]
. 将[65,97]放在49后面:[38,49,65,97]
. 其中,[13,76]和[27]的归并过程
. 13和27比较,13小,取出,余[76]和[27]
. 76和27比较,76大,取出27,放在13后面,余76
. 将76取出,放在27后面:13,27,76
参考代码
#include <stdio.h>
#include <stdlib.h>
void dis(int arr[], int len){
    int i = 0;    
    for(; i < len; i++){
        printf("%d ", arr[i]);
    }
    printf("\n");
}

void merge(int arr[],int temp[],int left,int mid,int right){
    // 标记左半区第一个未排序
    int l=left;
    // 标记右半区第一个未排序
    int r=mid+1;
    // 临时记录
    int pos=left;
    while(l<=mid && r<=right){
        if(arr[l]<arr[r]){
            temp[pos++]=arr[l++];
        }else{
            temp[pos++]=arr[r++];
        }
    }
    // 合并左半区剩下的
    while(l<=mid){
        temp[pos++]=arr[l++];
    }
    // 合并右半区剩下的
    while(r<=right){
        temp[pos++]=arr[r++];
    }
    // 合并后的复制回原数组
    while(left<=right){
        arr[left]=temp[left];
        left++;
    }
}
void ms(int arr[],int temp[],int left,int right){
    if(left<right){
        int mid=(left+right)/2;
        // 递归划分左半区
        ms(arr,temp,left,mid);
        // 递归划分右半区
        ms(arr,temp,mid+1,right);
        // 合并
        merge(arr,temp,left,mid,right);
    }
}
//主入口函数
void mergeSort(int arr[],int len){
    int* temp=(int*)malloc(len*sizeof(int));
    if(temp){
        ms(arr,temp,0,len-1);
        free(temp);
    }
}
int main () {
    int arr[]={9,5,2,7,12,4,3,1,11};
    int len=9;
    dis(arr,len);
    mergeSort(arr,len);
    dis(arr,len);
    return 0;
}            
特点
. 稳定
. 可用于链式存储
. 时间复杂度:O(nlogn)
. 空间复杂度:O(n):使用临时空间存储归并的记录