• 数据结构——归并排序


     这篇博客主要摘自https://www.cnblogs.com/chengxiao/p/6194356.html我又用C++重写了一下代码

    基本思想

      归并排序(MERGE-SORT)是利用归并的思想实现的排序方法,该算法采用经典的分治(divide-and-conquer)策略(分治法将问题(divide)成一些小的问题然后递归求解,而治(conquer)的阶段则将分的阶段得到的各答案"修补"在一起,即分而治之)。

    分而治之

       可以看到这种结构很像一棵完全二叉树,本文的归并排序我们采用递归去实现(也可采用迭代的方式去实现)。阶段可以理解为就是递归拆分子序列的过程,递归深度为log2n。

    合并相邻有序子序列

      再来看看阶段,我们需要将两个已经有序的子序列合并成一个有序序列,比如上图中的最后一次合并,要将[4,5,7,8]和[1,2,3,6]两个已经有序的子序列,合并为最终序列[1,2,3,4,5,6,7,8],来看下实现步骤。

    代码实现

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define maxn 500010
    #define ll long long int
    using namespace std;
    ll a[maxn];
    ll temp[maxn];
    ll sum;
    void Merge(int l,int r,int m)
    {
        int i=l;
        int j = m + 1;
        int k = l;
        while(i<=m&&j<=r)
        {
            if(a[i]>a[j])
            {
                //sum+=m-i+1;
                temp[k++]=a[j++];
            }
            else
            {
                temp[k++]=a[i++];
            }
        }
        while(i<=m)///将剩余的元素存到数组中
        {
            temp[k++]=a[i++];
        }
        while(j<=r)
        {
            temp[k++]=a[j++];
        }
        for(i=l; i<=r; i++)
        {
            a[i]=temp[i];
        }
    }
    void mergesort(int l,int r)
    {
        if(l<r)
        {
            int m = (l + r) / 2;
            mergesort(l,m);///左二分排序
            mergesort(m+1,r);///右二分排序
            Merge(l,r,m);///合并两个升序数组
        }
    }
    int main()
    {
        int n,i;
        while(scanf("%d",&n)!=EOF)
        {
            if(n==0)
            {
                break;
            }
            for(i=0; i<n; i++)
            {
                scanf("%lld",&a[i]);
            }
            sum=0;
            mergesort(0,n-1);
            for(i=0; i<n; i++)
            {
                printf("%lld ",a[i]);
            }
        }
        return 0;
    }

    执行结果

    [1, 2, 3, 4, 5, 6, 7, 8, 9]

    最后

      归并排序是稳定排序,它也是一种十分高效的排序,能利用完全二叉树特性的排序一般性能都不会太差。java中Arrays.sort()采用了一种名为TimSort的排序算法,就是归并排序的优化版本。从上文的图中可看出,每次合并操作的平均时间复杂度为O(n),而完全二叉树的深度为|log2n|。总的平均时间复杂度为O(nlogn)。而且,归并排序的最好,最坏,平均时间复杂度均为O(nlogn)。

  • 相关阅读:
    c#代码:使用假设的方法遍历解决“谁养鱼”问题(据说是爱因斯坦所出的一道推理题) 无为而为
    远洋地暖的使用步骤
    合伙人四大原则
    model y搭载60度磷酸铁锂电池的续航表现
    model3家用充电桩按220V还是380V区别?
    食用油的挑选标准
    职责链模式(Chain of Responsibility)
    通用数据链接(UDL)的用法
    Oracle REGEXP_INSTR 用法
    访问者模式(Visitor)
  • 原文地址:https://www.cnblogs.com/wkfvawl/p/9772447.html
Copyright © 2020-2023  润新知