归并排序

一、定义

基本思想

​ 归并排序,其基本思想是合并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

posted @ 2019-04-17 23:40  undifinedException  阅读(263)  评论(0编辑  收藏  举报