美文网首页
排序_二路归并排序

排序_二路归并排序

作者: Mad_Elliot | 来源:发表于2019-02-23 13:05 被阅读0次

    基本思想:把一个长度为n 的无序序列看成是 n 个长度为 1 的有序子序列 ,首先做两两归并,得到 [n / 2] 个长度为 2 的有序子序列 ;再做两两归并,…,如此重复,直到最后得到一个长度为 n 的有序序列。

    实现代码:

    一次二路归并算法:

    static void Merge(int[] a, int[] swap, int k, int n)
    {//swap用于存放一次归并后的数组,k为有序子数组长度,n为数组大小
    
        int i, j, low1, up1, low2, up2, m;
        low1 = 0; //第一个子数组下界为0
        m = 0;  //swap数组下标
        while (low1 + k <= n - 1)
        {
            low2 = low1 + k;//第二个子数组下界
            up1 = low2 - 1; //第一个子数组上界
            //第二个子数组上界需要考虑是否超出数组范围,超出则直接等于最后下标
            up2 = (low2 + k - 1 <= n - 1) ? low2 + k - 1 : n - 1;
            //同时遍历两个子数组,直到任意一个遍历完
            for (i = low1, j = low2; i <= up1 && j <= up2; m++)
            {//从小到大依次存到swap数组中
                if (a[i] <= a[j])
                {
                    swap[m] = a[i];
                    i++;
                }
                else
                {
                    swap[m] = a[j];
                    j++;
                }
            }
            //将未遍历完的子数组剩下的元素存放到swap中
            while (i <= up1)
            {
                swap[m] = a[i];
                m++;
                i++;
            }
            while (j <= up2)
            {
                swap[m] = a[j];
                m++;
                j++;
            }
    
            low1 = up2 + 1;//跳到下两个子数组,循环继续
        }
        //把剩下只够一组的数据依次放到swap的最后面
        for (i = low1; i < n; i++, m++)
        {
            swap[m] = a[i];
        }
    }
    

    二路归并算法:

    static void MergeSoprt(int[] a, int n)
    {
        int i, k = 1;
        int[] swap = new int[n];
        while (k < n)
        {
            Console.WriteLine("有序子数组长度 = " + k);
            Merge(a, swap, k, n);
            for (i = 0; i < n; i++)
            {
                a[i] = swap[i];
                Console.Write(a[i] + " ");
            }
            Console.WriteLine();
            k *= 2;
        }
    }
    

    测试代码:

    static void Main(string[] args)
    {
        int[] nums = { 21, 25, 49, 25, 93, 62, 72, 8, 37, 16, 54 };
        MergeSoprt(nums, nums.Length);
    
        Console.ReadKey();
    }
    

    总结:
    1、合并就是两个数组里的元素相互比较,从小到大存到一个新数组中;
    2、时间效率: O(nlog2n)
    3、稳定性:稳定


    最后总结:

    思考:
    1、若初始记录基本有序,则选用哪些排序方法比较适合?
    答:可选用直接插入、简单选择、堆排序、冒泡排序、归并排序、(希尔排序)等方法,其中最快的是
    插入排序和冒泡排序,因为只有比较动作,无需移动元素。此时平均时间复杂度为O(n)。
    2、若初始记录基本无序,最好选用哪些排序方法?
    答:最好选用快速、希尔、归并、堆排序等,这些算法的共同特点是,通过“振荡”让数值相差不大但位置差异很大的元素尽快到位。

    相关文章

      网友评论

          本文标题:排序_二路归并排序

          本文链接:https://www.haomeiwen.com/subject/hmpuyqtx.html