内部排序(四)归并排序

总述:归并排序(Merging Sort)中归并是将两个或两个以上的有序表组合成一个新的有序表。
归并排序我们主要探讨2-路归并排序
2-路归并排序 过程:假设初始序列含有n个记录,则可看成是n个有序的子序列,每个子序列的长度为1,然后两两归并,得到ceil(n/2)个长度为2或1的有序子序列;再两两归并,……如此重复,直至得到一个长度为n的有序序列为止。
2-路归并排序 过程演示
这里写图片描述

算法叙述
2-路归并排序中的核心操作是 归并操作,将一维数组中前后相邻的两个有序子序列归并为一个有序序列,其算法:

1、 申请空间,使其大小为两个已经排序序列之和,该空间用来存放合并后的序列
2、设定两个指针,最初位置分别为两个已经排序序列的起始位置
3、比较两个指针所指向的元素,选择相对小的元素放入到合并空间,并移动指针到下一位置
4、重复步骤3直到某一指针到达序列尾
5、将另一序列剩下的所有元素直接复制到合并序列尾

算法代码

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

#define MAXSIZE 20
typedef int KeyType;//定义关键字类型为int
typedef char InfoType;//定义其他信息类型为char

typedef struct{//定义记录类型
    KeyType key;
    InfoType otherinfo;
}RedType;
typedef struct{//定义顺序表类型
    RedType r[MAXSIZE + 1];//r[0]闲置或作为哨兵
    int length;//顺序表的长度
}SqList;


//此函数将两个相邻有序子序列SR[1...m]和SR[m+1...n]合并成一个有序的TR[i...n]
void Merge(RedType SR[], RedType TR[], int i, int m, int n){
    int j, k;
    //i指向子序列SR[1...m],j指向子序列SR[m+1...n],k指向合并序列TR[i...n]
    for (j=m+1,k=i;j<=n&&i<=m; k++){
        if (SR[i].key<SR[j].key){//比较,将小的放入合并序列TR
            TR[k] = SR[i++];//把子序列值放到合并序列后,指针向后移动
        }
        else{
            TR[k] = SR[j++];//把子序列值放到合并序列后,指针向后移动
        }
    }
    //将剩下的多余记录直接放到合并序列尾部
    if (i<=m){//若子序列SR[1...m]有剩余
        for (int x = i; x <= m; x++){
            TR[k++] = SR[x];
        }
    }
    if (j<=n){//若子序列SR[m+1...n]有剩余
        for (int x = j; x <= m; x++){
            TR[k++] = SR[x];
        }
    }

}

//此函数将SR[s...t]归并为TR1[s...t]
void MSort(RedType SR[], RedType TR1[], int s, int t){
    int m;

    if (s==t){//当每个子序列只有一个记录时,直接将SR归并到TR1,递归终止
        TR1[s] = SR[s];
    }else{
        m = (s + t) / 2;//将SR[s...t]平分为SR[s...m]和SR[m+1...t]
        MSort(SR, TR2, s, m);//递归地将SR[s...m]归并为有序的TR2[s...m]
        MSort(SR, TR2, m + 1, t);//递归地将SR[m+1...t]归并为有序的TR2[m+1...t]
        Merge(TR2, TR1, s, m, t);//将TR2[s...m]和TR2[m+1...t]归并到TR1[s...t]
    }
}

//对顺序表L作归并排序
void MergeSort(SqList *L){
    MSort(L->r, L->r, 1, L->length);
}

评价
1、实现归并排序需和待排记录等数量的辅助空间,其时间复杂度为O(nIogn)
2、与快速排序和堆排序相比,归并排序最大的特点是,它是一种稳定排序方法,
2、递归形式的算法形式上较为简洁,但实用性很差!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值