排序算法之二路归并排序

排序算法之二分归并排序

  • 上学期的数据结构已经讲过归并排序了,但是上学期太懒了,所以没有动手把代码写出来2333。今天在写算法设计的第二章作业,讲的是分治思想。而归并排序的思想就是分治,便乘此机会动手实际写一下归并排序。

  • 大学入学以来好吃懒做,算法方面根本没有什么进步,排序还只会高中学的冒泡排序和选择排序…在之后的学习生活中,一定要重视算法,动手实操并真正理解算法。

  • 以下是我写的二分归并排序的代码

    #include <iostream>
    #include <cstdlib>
    #include <ctime>
    using namespace std;
    
    int a[11] = {0};
    int b[11] = {0};
    
    void Merge(int a[], int low, int mid, int high)
    {
        int i = low, j = mid + 1, k = low; //分别代表需要归并的的左部分的初始坐标i,右部分的初始坐标j,以及辅助数组的初始坐标k
        while (i <= mid && j <= high)
        {
            if (a[i] <= a[j]) //左半部分的值比较小,存入辅助数组之中
                b[k++] = a[i++];
            else
                b[k++] = a[j++];
        }
        while (i <= mid) //将a中左部分和右部分的剩余元素依次存入辅助数组之中,当然这个和接下来的while循环很显然只能运行一个,因为左部分和右部分当中的一个已经全部加入辅助数组中了,不然是跳不出上一个while循环的
            b[k++] = a[i++];
        while (j <= high)
            b[k++] = a[j++];
        for (int index = low; index <= high; index++)
            a[index] = b[index]; //用辅助数组已经有序的值,把原始数组进行覆盖,最后的a数组就是merge之后有序的了
    }
    void MergeSort(int a[], int low, int high)
    {
        if (low < high) //很重要,避免出现low = high导致死循环局面的发生,实际上也是往深层次递归的终止条件
        {
            int mid = (low + high) >> 1;
            MergeSort(a, low, mid); //分治的思想,划分子问题
            MergeSort(a, mid + 1, high);
            Merge(a, low, mid, high); //将之前划分出来的两个子问题进行合并,得到最终有序的序列
        }
        return;
    }
    int main()
    {
        srand(time(0));
        for (int i = 0; i < 11; i++) //产生随机数
        {
            a[i] = rand() % 20;
            cout << a[i] << " ";
        }
        cout << endl;
        MergeSort(a, 0, 10);
        for (int i = 0; i < 11; i++)
            cout << a[i] << " ";
        cout << endl;
        return 0;
    }
    
  • 其中的MergeSort函数会把问题规模从原来的(low,high)分成两个部分,分别是(low,mid)和(mid+1,high),进行递归,而子问题也会继续向下递归,直到low == high也就是某个部分中只有一个元素了。

  • 以下是我画的递归图

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4PP3F4PL-1618239042418)(排序算法之二路归并排序.assets/1.jpg)]

  • 最后画出来就像一棵树,我们进行的操作仿佛就是树的后序遍历(也就是最后访问根节点)。我们可以把左子问题理解为左子树,右子问题理解为右子树,最后的把两个子问题进行归并的操作理解为访问根节点。

  • 这里我举一个例子方便理解。MS(a,0,10)会一直向深层次递归,经过MS(a,0,5),接着为MS(a,0,2),然后为MS(a,0,1),最后是MS(a,0,0),然后因为这时候low == high,所以我们会直接renturn(程序28行和35行)。然后到达了MS(a,1,1,),同样return,相当于已经访问完毕了MS(a,0,1)的左子树和右子树,接下来我们需要把这两个子问题进行归并,理解为访问根节点。

  • 这里我还想要说一点,左右子问题的规模可能是不一样的,比如MS(a,0,2)这个问题中,左子问题的规模为2,而右子问题的规模是1,但是由于我们Merge归并函数写的好,所以可以正常归并2333

  • 实际运行结果

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-OnqKcQzr-1618239042420)(排序算法之二路归并排序.assets/2.png)]

  • 参考链接

  • 二分归并排序算法分析_m0_46419294的博客-CSDN博客_二分归并排序算法

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值