归并排序

归并排序

归并排序是建立在归并操作上的一种有效,稳定的排序算法。该算法采用分治策略,是分治策略在算法设计中的一个典型应用。
归并算法原理:将序列一分为二,子序列递归排序,合并有序子序列,最终得到一个有序的序列。

图例分析:
在这里插入图片描述
上图为归并排序的分割和归并过程。
归并原理:分别从两个已排序的序列头部(序列的最小值位置)开始,顺次比较,将较小者写入存储序列,较小者位置向后移动一位,继续与另一个序列的最小值比较,以此轮推,知道将两个序列内的数据全部写入存储序列。
如下图:
在这里插入图片描述
递归实现:

    public void TestSort()
    {
        int[] arr = new int[] { 5, 9, 2, 0, 7, 6 };
        MergeSortFun(arr, 0, arr.Length - 1);
    }

    public void MergeSortFun(int[] arr, int left, int right)
    {
        int[] tempArr = new int[arr.Length];
        MergeSortFun(arr, left, right, tempArr);
    }

    private void MergeSortFun(int[] arr, int left, int right, int[] tempArr)
    {
        if (right <= left)
        {
            return;
        }

        int mid = (left + right) >> 1;

        MergeSortFun(arr, left, mid, tempArr);
        MergeSortFun(arr, mid + 1, right, tempArr);
        Merge(arr, left, mid, right, tempArr);
    }

    private void Merge(int[] arr, int left, int mid, int right, int[] tempArr)
    {
        // 将左侧数据拷贝到 tempArr
        for (int n = left; n <= mid; ++n)
        {
            tempArr[n] = arr[n];
        }

        //令 i : 从 tempArr 第 left    个元素开始,到 mid(包含mid)结束
        //令 j : 从 arr     第 mid + 1 个元素开始,到 right(包含right)结束
        //令 t : 从 arr     第 left    个元素开始,到 right(包含right)结束
        //按照上面顺序依次比较,将 tempArr[i]、arr[j] 中较小者放入到 arr[t] 中, t++, 较小者为 tempArr[i]则 i++,较小者为 arr[j]则 j++; 

        for (int i = left, t = left, j = mid + 1; i <= mid;)
        {
            //如果 j > right,说明已经到末尾了,剩下的无需在比较,则直接将 tempArr中从 i 到 mid 的数据拷贝到 arr 中即可
            //否则 如果tempArr[i] < arr[j],将 tempArr[i] 拷贝到 arr 中

            //完整判断应该如下:
            //if ((i <= mid) && (j > right || tempArr[i] < arr[j]))
            //因为 for 循环中已经限制了 (i <= mid),所以此处该限制可以省略
            if ((j > right) || (tempArr[i] <= arr[j]))
            {
                arr[t] = tempArr[i];
                ++t;
                ++i;
            }

            //如果 j 右侧没有到末尾,则将 满足条件的 arr[j] < tempArr[i],拷贝到 arr[t]
            //完整判断应该如下:
            //因为 for 循环已经限制了 (i <= mid),所以此处 不会触发 i > mid 的条件
            //if ((j <= right) && ((i > mid) || arr[j] < tempArr[i]))
            if ((j <= right) && (arr[j] <= tempArr[i]))
            {
                arr[t] = arr[j];
                ++t;
                ++j;
            }
        }
    }

性能分析:
该算法在任何情况下的总体迭代为 N 次,时间复杂度为 O(nlogn),并且最坏和最好情况下的时间复杂度都是一样的。
因为需要申请一个临时的长度为 N 的空间存放数据,所以空间复杂度为 O(n).

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值