归并排序

来源:互联网 发布:局域网未识别的网络 编辑:程序博客网 时间:2024/06/13 18:37
 研究过归并排序和堆排序的时间复杂度的朋友们应该知道它们的时间复杂度都是nlog2n。堆排序是利用了完全二叉树,做了很多次堆调整才达到了排序的目的。相关堆排序的内容可以看看选择排序的升级---堆排序,在此不多赘述。
   其实归并排序也是形似二叉树。简单来讲就是分而治之的思想。谈到 ‘分’很容易想到快速排序,快排也是分。但它是把数列从枢轴点分开。让点的边左都小 右边都大(降序则相反) ,快排分的关键点在于枢轴点的筛选。而归并排序的 ‘分’ 只是归并的一部分。‘分’是为了归并。简单来说,如果我要让两个数列归并成一个有序数列的前提 是 你给我的两个数列得本来就是有序的。如何保证给的两个数列是有序的呢?那就得保证 这两个数列 分别又是各由两个有序列归并来的。
那么这岂不是无穷无尽了吗?其实是有尽头的。那就是如果某个数列长度为2。那么它就是由两个数字归并来的。这两个数字分别都是有序的。一个数字就是有序的啊!
所以归并的前提是一直把数列两两划分。分到不能分的程度的时候我们再使用归并。

代码如下:



Merge部分的代码为归并,它让以s下标为开头,e下标为结尾 中间m下标为分界点的两个数组归并(其实是整个 arr 数组中的一段数组,我们看作是以m划分的两段)。归并算法很简单。因为两个数组分别都有序了,我们只要从任意数组A或B开始,下标为i和j。让i下标和j下标对应的值比较,谁小就放在临时数组tmp中。直到某一个下标到终点了(i的终点为m,j的终点为e)。我们不用比较了,然后让那个没到终点的下标,到终点,并把值放到tmp里。最后tmp里就是个有序数列了,把tmp在全部覆盖给我要需要排序的arr里。
示意图:

MergerSort里的除过Merge的部分其实就是递归划分。一层层递归下去后,当s>=e的时候。即数列的开始下标没有末尾下标大了。那就是开始下标和末尾下标相等了,代表已经划分成了一个数字的地步了,就不需要继续分了。然后递归结束一层层收回,收回的时候都会执行Merge(arr,tmp,s,mid,e);语句,就会往回归并。
 示意图:  



10万个随机数据测试结果:


最后时间复杂度均为O(nlog2n)    空间复杂度为O(N)
值得注意的是 稳定性是稳定的。
原创粉丝点击