排序算法---归并排序

1. 归并操作

归并排序是在归并操作上实现的。先了解一下归并操作的原理。

归并操作:将两个有序数组合并为一个新的有序数组。

如有序数组A=[1, 4, 6], B=[2, 4, 5],将其进行合并。设置变量下标i和j分别表示数组A和B的下标。遍历完数组A和B,最终合并后数组为C。

  • 若A[i] <= B[j],则将A[i]保存到数组C,并将i++;
  • 若A[i] > B[j],则将B[j]保存到数组C,并将j++;

归并操作的具体实现如下:

void Merge(int *piArrayA, int iArrayALen, int *piArrayB, int iArrayBLen, int *piArrayC)
{
    int iIndex1 = 0;        /* 指向数组A下标 */
    int iIndex2 = 0;        /* 指向数组B下标 */
    int iIndex3 = 0;        /* 指向数组C下标 */

    while ((iIndex1 < iArrayALen) || (iIndex2 < iArrayBLen))
    {
        if ((iIndex1 < iArrayALen) 
        && ((iIndex2 >= iArrayBLen) || (piArrayA[iIndex1] < piArrayB[iIndex2]))
        {
            /* 当数组A还没遍历完时,若数组B已经遍历完或者当前数组A的值小于数组B的值,则将当前数组A的值保存到新数组C */
            piArrayC[iIndex3++] = piArrayA[iIndex1];
            /* 将数组A下标前移 */
            iIndex1++;
        }
        else
        {
            /* 其他情况将当前数组B的值保存到新数组C */
            piArrayC[iIndex3++] = piArrayB[iIndex2];
            /* 将数组B下标前移 */
            iIndex2++;
        }
    }

    return;
}

2. 归并排序

归并排序是在归并操作基础上实现的。由于归并操作的前提是数组有序,因此我们可以考虑将待排序数组一分为二,先将一分为二的两个子数组变得有序后,再利用归并操作合并该两个子数组,此时整个数组将变得整体有序。

基于上述思想,我们使用递归操作,持续将数组一分为二,将数组划分得只有一个元素时,其将变得天然有序,此时将其合并,层层操作,最终将实现整个数组排序。

具体代码如下:

/* 归并操作 */
void Merge(int *piArrayA, int iArrayALen, int *piArrayB, int iArrayBLen, int *piArrayC)
{
    int iIndex1 = 0;        /* 指向数组A下标 */
    int iIndex2 = 0;        /* 指向数组B下标 */
    int iIndex3 = 0;        /* 指向数组C下标 */

    while ((iIndex1 < iArrayALen) || (iIndex2 < iArrayBLen))
    {
        if ((iIndex1 < iArrayALen) 
        && ((iIndex2 >= iArrayBLen) || (piArrayA[iIndex1] < piArrayB[iIndex2]))
        {
            /* 当数组A还没遍历完时,若数组B已经遍历完或者当前数组A的值小于数组B的值,则将当前数组A的值保存到新数组C */
            piArrayC[iIndex3++] = piArrayA[iIndex1];
            /* 将数组A下标前移 */
            iIndex1++;
        }
        else
        {
            /* 其他情况将当前数组B的值保存到新数组C */
            piArrayC[iIndex3++] = piArrayB[iIndex2];
            /* 将数组B下标前移 */
            iIndex2++;
        }
    }

    return;
}

/* 归并排序 */
/* 递归操作 */
void MergeSort(int *piNums, int iNumsSize)
{
    int iMiddle = 0;
    int aiLeftArray[iNumsSize];
    int aiRightArray[iNumsSize];

    if (iNumsSize <= 1)
    {
        /* 当数组最多只有1个元素时,其天然变得有序,此时结束递归 */
        return;
    }

    iMiddle = iNumsSize / 2;
    /* 先将数组一分为二,分别递归 */
    /* 左闭右开区间原则 */
    /* 对数组左半部分排序 */
    memset(aiLeftArray, 0, sizeof(aiLeftArray));
    memcpy(aiLeftArray, piNums, sizeof(int) * iMiddle);
    MergeSort(aiLeftArray, iMiddle); 

    /* 对数组右半部分排序 */ 
    memset(aiRightArray, 0, sizeof(aiRightArray));
    memcpy(aiRightArray, piNums + iMiddle, sizeof(int) * (iNumsSize - iMiddle));
    MergeSort(aiRightArray, iNumsSize - iMiddle);   

    memset(piNums, 0, sizeof(int) * iNumsSize);
    /* 对排好序的左右半部分数组进行归并操作 */
    Merge(aiLeftArray, iMiddle, aiRightArray, iNumsSize - iMiddle, piNums);

    return;
}

从上可以看出,归并排序利用的是分治思想。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值