归并排序(Merge Sort)

来源:互联网 发布:网店系统源码 编辑:程序博客网 时间:2024/06/01 07:32

算法描述:建立在归并操作上的一种有效的排序算法,其是采用分治法(Divide and Conquer)的一个非常典型的应用。归并排序的动态图示如下所示:
  这里写图片描述

复杂度分析:最坏时间复杂度为O(NlogN),平均时间复杂度也为O(NlogN),效率较高。

主要特点:

  • 稳定;
  • 占用额外内存O(N)
  • 核心在于有序子列的合并;
  • 可以用递归方式实现,也可以用非递归方式实现。

C语言描述(递归算法):

#include<stdio.h>#include<stdlib.h>typedef int ElementType;void Swap(ElementType *A, ElementType *B) {    ElementType temp = *A;    *A = *B;    *B = temp;}/* 有序子列的合并:Left、Right和RightEnd分别为左边起始位置、右边起始位置和右边终点位置 */void Merge(ElementType Data[], ElementType Temp[], int Left, int Right, int RightEnd) {    int i;    int LeftEnd = Right - 1;     int temp = Left;    int num = RightEnd - Left + 1;    while (Left <= LeftEnd && Right <= RightEnd) { /*左右两边均有元素*/        if (Data[Left] <= Data[Right]) Temp[temp++] = Data[Left++];        else Temp[temp++] = Data[Right++];    }    while (Left <= LeftEnd)     Temp[temp++] = Data[Left++]; /*直接复制左边元素*/    while (Right <= RightEnd)   Temp[temp++] = Data[Right++]; /*直接复制右边元素*/    // 将Temp[]中的元素复制到Data[]中    for (i = 0; i < num; i++)   Data[RightEnd] = Temp[RightEnd--];}/* 核心递归排序函数:分而治之 T(N)=O(NlogN) */void MSort(ElementType Data[], ElementType Temp[], int Left, int RightEnd) {    int Center;    if (Left < RightEnd) {        Center = (Left + RightEnd) / 2;         MSort(Data, Temp, Left, Center); /*递归解决左边*/        MSort(Data, Temp, Center + 1, RightEnd); /*递归解决右边*/        Merge(Data, Temp, Left, Center + 1, RightEnd); /*合并两段有序序列*/    }}/* 归并排序C语言描述(递归方式) */void Merge_Sort(ElementType Data[], int N) {    /* 在此声明额外空间的好处? */    ElementType *Temp = (ElementType*)malloc(N*sizeof(ElementType));    if (Temp != NULL) {        MSort(Data, Temp, 0, N - 1);        free(Temp);    }    else printf("空间不足");}int main() {    ElementType Data[] = {28, 3, 33, 23, 15, 30, 19, 10, 20, 22 };    Merge_Sort(Data, 10);    return 0;}

C语言描述(非递归算法):

#include<stdio.h>#include<stdlib.h>typedef int ElementType;void Swap(ElementType *A, ElementType *B) {    ElementType temp = *A;    *A = *B;    *B = temp;}/* 有序子列的合并:Left、Right和RightEnd分别为左边起始位置、右边起始位置和右边终点位置 */void Merge(ElementType Data[], ElementType Temp[], int Left, int Right, int RightEnd) {    int i;    int LeftEnd = Right - 1;     int temp = Left;    int num = RightEnd - Left + 1;    while (Left <= LeftEnd && Right <= RightEnd) { /*左右两边均有元素*/        if (Data[Left] <= Data[Right]) Temp[temp++] = Data[Left++];        else Temp[temp++] = Data[Right++];    }    while (Left <= LeftEnd)     Temp[temp++] = Data[Left++]; /*直接复制左边元素*/    while (Right <= RightEnd)   Temp[temp++] = Data[Right++]; /*直接复制右边元素*/    // 将Temp[]中的元素复制到Data[]中    for (i = 0; i < num; i++)   Data[RightEnd] = Temp[RightEnd--];}/* 两两归并相邻有序子列:length为当前有序子列的长度 */void Merge_pass(ElementType Data[], ElementType Temp[], int N, int length) {    int i, j;    for (i = 0; i + 2 * length <= N; i += 2 * length)          Merge(Data, Temp, i, i + length, i + 2 * length - 1);    if (i + length < N) /*归并最后2个子列*/        Merge(Data, Temp, i, i + length, N - 1);    else /*最后只剩1个子列*/    for (; i < N; i++) Temp[i] = Data[i];}/* 归并排序C语言描述(非递归方式) */void Merge_Sort(ElementType Data[], int N) {    int length = 1; /*初始化子序列长度*/    ElementType *Temp = (ElementType*)malloc(N*sizeof(ElementType));    if (Temp != NULL) {        while (length < N) {            Merge_pass(Data, Temp, N, length);            length *= 2;            Merge_pass(Temp, Data, N, length);            length *= 2;        }        free(Temp);    }    else printf("空间不足");}int main() {    ElementType Data[] = {28, 3, 33, 23, 15, 30, 19, 10, 20, 22 };    Merge_Sort(Data, 10);    return 0;}
原创粉丝点击