• 归并排序


    一、定义

    基本思想

    ​ 归并排序,其基本思想是合并2个已经排序的表,因为2个表已经排序,所以合并时,将数据放到第三个表中,则该算法可以通过对输入数据一样排序来完成。

    • 基本的算法是取2个输入数组A和B,一个输出数组C。
    • 3个计数器,Actr,Bctr,Cctr,他们初始置于对应数组的开始端。
    • A[Actr]和B[Bctr]中较小者拷贝到C中的下一个位置,相关计数器向前推进一步。
    • 当一个表有一个用完的时候,则将另一个表中剩余部分拷贝到C中。

    图解

    过程描述

    ​ 基本过程如图所示,将两个已经排序的数组进行合并。每次比较之后将小的元素拷贝到C,知道A指针到最后。B数组无从比较,因为A和B都已经排序,所以直接将B最后都数字拷贝到C。

    编程描述

    ​ 实际问题中,我们处理一个未排序的数组,怎么用它来实现排序呢,因为程序的目的是处理一个数组,而不是2个已排序的数组。例如,程序将数组a={24,13,26,1,2,27,38,15}排序,我们应当如何用程序描述这一过程。

    ​ 这里采用一个实际经常使用的方法:分治策略

    • 使用递归将前4个数字和后4个数字排序:1,13,24,26,2,15,27,38。
    • 再合并这两部分。

    二、算法分析

    ​ 这里采用递归的程序实现,根据策略是分治的方法。而且是对半递归。我们可以很简单的分析其时间。

    [T(1)=1\ T(N)=2T(N/2)+N\ ]

    ​ 对上述公式的说明和求解:当N=1,即只有1个元素的时候,我们需要时间是1。当N个元素时,需要先处理前1/2和后面1/2。最后将所有的N拷贝一份。所以得到(T(N)=2T(N/2)+N)

    [T(N)=2T(N/2)+N\ frac{T(N/2)}{N/2}=frac{T(N/4)}{N/4}+1\ frac{T(N/4)}{N/4}=frac{T(N/8)}{N/8}+1\ ·\ ·\ ·\ frac{T(2)}{2}=frac{T(1)}{1}+1 ]

    ​ 然后使用叠缩求和:将方程左边和右边相加,消去相等项,并且容易知道一共(logN)个方程。得到:

    [frac{T(N)}{N}=frac{T(1)}{1}+logN ]

    ​ 最后得到:(T(N)=NlogN+N=O(NlogN))

    结论

    • 所以我们得到归并排序最后的时间为(O(NlogN))

    • 但是它有一个明显的缺陷是:需要创建数组并拷贝。拷贝为常数时间,但是创建一个数组,额外增加了它的内存开销。

    ​ 但是对数组的拷贝和内存的开辟,不同的语言是不一样的。例如:Java的引用对象排序时,拷贝数组,只是拷贝其对象的引用。只涉及到引用的赋值。所以归并排序作为Java范型排序的算法

    ​ 而C++的范型排序则不同,如果拷贝的对象过于庞大,那会产生很大的时间和内存开销。是不能接受的。

    三、代码地址

    https://github.com/dhcao/dataStructuresAndAlgorithm/blob/master/src/chapterSeven/MergeSortEx.java

  • 相关阅读:
    Don‘t Cry for Me, Argentina
    对象池
    拒绝高姿态
    SOS: How to popup a HwndSource on topmost
    关于设计和设计文档的2个补充
    从今天开始写博客
    Kafka+Storm写入Hbase和HDFS
    工作流调度引擎Oozie
    showModalDialog在父窗体和子窗体之间传值
    慢说HttpContext
  • 原文地址:https://www.cnblogs.com/dhcao/p/10727077.html
Copyright © 2020-2023  润新知