34. 排序算法(7):归并排序的递归实现

1. 基本原理

  归并排序 (Merge Sort) 就是利用归并的思想实现的排序方法。他的原理是假设初始序列有 n 个记录,则可以看成是 n 个有序的子序列,每个子序列的长度为1,然后两两归并,得到 n/2 ⌈ n / 2 ⌉ 个长度为1 或者2 的有序子序列;再两两归并,……,如此重复,直至得到一个长度为 n 的有序序列为止,这种排序 方法称为 2 路归并排序。

  具体过程如下图所示

  首先将数组两两进行排序,之后将得到的结果在再两两排序,之后再两两排序,直至整个数组排序完成。所以从算法的简单描述就可以看出,一种直觉的方法就是使用递归,但是我们这里也会同时介绍一种使用迭代的方法。

2. 代码实现

2.1 递归实现方法

  

#include <stdio.h>
#define MAXSIZE 10

// 实现归并,并把最后的结果存放到list1里
void merging(int *list1, int list1_size, int *list2, int list2_size)
{
    int i, j, k, m;
    int temp[MAXSIZE];

    i = j = k = 0;      // i 是 list 1 的下标,j 是 list 2 的下标,k 是索引临时变量 temp 的

    while( i < list1_size && j < list2_size )
    {
        if( list1[i] < list2[j] )
        {
            temp[k++] = list1[i++];
        }
        else
        {
            temp[k++] = list2[j++];
        }
    }

    将最大的依次追加在 temp 的尾部
    while( i < list1_size )
    {
        temp[k++] = list1[i++];
    }

    while( j < list2_size )
    {
        temp[k++] = list2[j++];
    }

    // 将 temp 中所有的元素放入 list1 中
    for( m=0; m < (list1_size + list2_size); m++ )    
    {
        list1[m] = temp[m];
    }
}

void MergeSort(int k[], int n)
{
    if( n > 1)   // 递归停止的参数
    {
        int *list1 = k;          // 左半部分
        int list1_size = n/2;    // 左半部分的尺寸
        int *list2 = k + n/2;    // 右半部分
        int list2_size = n - list1_size;    // 右半部分的尺寸

        MergeSort(list1, list1_size);    // 递归调用自己
        MergeSort(list2, list2_size);

        merging(list1, list1_size, list2, list2_size);    //实现归并
    }
}

int main()
{
    int i, a[10] = {5, 2, 6, 0, 3, 9, 1, 7, 4, 8};

    MergeSort(a, 10);

    printf("排序后的结果是:");
    for( i=0; i < 10; i++ )
    {
        printf("%d", a[i]);
    }
    printf("\n\n");

    return 0;
}

2.2 代码相关解释

  在上述的代码中,比较难理解的部分是void merging(),现在以最简单的情况模拟计算机对这部分代码进行执行。假设现在在 list1 和 list2 中都只有一个元素,如 list1 = {4}list2 = {2}。在第一个 while 循环中,其中的void merging(temp[k++] = list1[i++])实际上先进行temp[k] = list1[i],再进行k++i++,所以第一个 while 循环是将两个元素之中较大的放入临时数组中,剩下的两个 while 循环是将最大的元素追加在数组的尾部,最后的是将临时存储的数组用 list1 进行保存。

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值