归并排序

下面是归并排序的一些特征:

  • 时间复杂度,最好最坏平均都为:O(nlog2n)
  • 空间复杂度,最好最坏平均都为:O(n)
  • 是否稳定:稳定

二路归并的时间复杂度为O(nlog2n),多路归并排序在引入败者树后也为O(nlog2n)

只有在最后一次排序后才每个元素才确定是在最终位置

归并的含义是将两个或两个以上的有序表组合成一个新的有序表
2路归并排序的基本思想:将初始待排序的每个元素都看成是一个排好序的子表,然后两两归并,得到n/2个长度为2或1的有序表;再两两归并,如此重复,直到合并为长度为n的有序表为止

下面是2路归并排序的代码:

void merge_sort(int arr[], int low, int high)
{
    if (low < high) {
        int mid = (low+high)/2;         // 从中间划分两个子序列
        merge_sort(arr, low, mid);      // 对左侧子序列进行递归排序
        merge_sort(arr, mid+1, high);   // 对右侧子序列进行递归排序
        merge(arr, low, mid, high);     // 归并
    }//if
}

/**
* 合并两个有序表
*/
void merge(int arr[], int low, int mid, int high)
{
    // arr[low...mid]与arr[mid+1...high]各自有序,将他们合并
    int i, j, k;
    for (k=low; k<=high; k++)
        arr_bk[k] = arr[k];     // 将arr中的所有元素复制到arr_bk中
    for (i=low, j=mid+1, k=i; i<=mid&&j<=high; k++) {
        if (arr_bk[i] <= arr_bk[j])
            arr[k] = arr_bk[i++];
        else
            arr[k] = arr_bk[j++];
    }//for
    while (i<=mid)  arr[k++] = arr_bk[i++]; // 若第一个表未检测完,复制
    while (j<=high) arr[k++] = arr_bk[j++]; // 若第二个表未检测完,复制
}

测试代码,可直接复制后编译执行:

#include <stdio.h>
#include <stdlib.h>

void show(int arr[], int len);
void merge_sort(int arr[], int low, int high);
void merge(int arr[], int low, int mid, int high);

int * arr_bk;   // 辅助排序的数组

int main()
{
    const int len = 7;
    int arr[len] = {7, 10, 11, 9, -8, 2, 27};
    arr_bk = (int *)malloc(sizeof(int)*len);
    merge_sort(arr, 0, len-1);
    free(arr_bk);
    show(arr, len);
    return 0;
}

void show(int arr[], int len)
{
    int i;
    for (i=0; i<len; i++) {
        printf("%4d", arr[i]);
    }
    printf("
");
}

void merge_sort(int arr[], int low, int high)
{
    if (low < high) {
        int mid = (low+high)/2;         // 从中间划分两个子序列
        merge_sort(arr, low, mid);      // 对左侧子序列进行递归排序
        merge_sort(arr, mid+1, high);   // 对右侧子序列进行递归排序
        merge(arr, low, mid, high);     // 归并
    }//if
}

/**
* 合并两个有序表
*/
void merge(int arr[], int low, int mid, int high)
{
    // arr[low...mid]与arr[mid+1...high]各自有序,将他们合并
    int i, j, k;
    for (k=low; k<=high; k++)
        arr_bk[k] = arr[k];     // 将arr中的所有元素复制到arr_bk中
    for (i=low, j=mid+1, k=i; i<=mid&&j<=high; k++) {
        if (arr_bk[i] <= arr_bk[j])
            arr[k] = arr_bk[i++];
        else
            arr[k] = arr_bk[j++];
    }//for
    while (i<=mid)  arr[k++] = arr_bk[i++]; // 若第一个表未检测完,复制
    while (j<=high) arr[k++] = arr_bk[j++]; // 若第二个表未检测完,复制
}
原文地址:https://www.cnblogs.com/qijinzhi/p/merge_sort.html