并归排序是学习分治法 (Merge Sort) 的好例子。而且它相对于选择,插入,冒泡排序来说,算法性能有一定提升。我首先会描述要解决的问题,并给出一个并归排序的例子。之后是算法的思路以及给出伪代码。算法的实现部分用Python完成。最后自己尝试说明白算法分析。
问题描述
问题描述很简单,输入一组未排序的数组,如左边的数组,通过并归排序算法的计算,输出一组正确排序的数组,如右边的数组。
如果利用上面这个例子来做并归排序的话,应该首先将该数组切割成两半,对左边一半进行排序,在对右边一半进行排序,在合并排序好的左右数组。如下图所示:
思路和伪代码
可以从例子中看出,并归排序就是一个先分后合的过程:
- 递归排序左半部分数组;
- 递归排序右半部分数组;
- 合并 (Merge) 这两部分生成最后结果。
合并 (Merge)过程的核心思想就是:给左右两个数组分别设定一个标记符号i和j,通过比对当前i和j位置的数的大小,选择小的值加入到最后的结果中去。
合并(Merge) 的伪代码:
1 C = output[length=n] 2 A = 1st sorted array[n/2] 3 B = 2st sorted array[n/2] 4 i = 1 5 j = 1 6 for k=1 to n 7 if A(i) < B(j) 8 C(k) = A(i) 9 i++ 10 else B(j) < A(i) 11 C(k) = B(j) 12 j++ 13 end
算法实现
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 def merge(left, right): 2 result = [] 3 i, j=0, 0 4 ll, lr = len(left), len(right) 5 while i < ll and j < lr: 6 if i < ll and j < lr: 7 if left[i] < right[j]: 8 result.append(left[i]) 9 i = i+1 10 else: 11 result.append(right[j]) 12 j =j+1 13 result+=left[i:] 14 result+=right[j:] 15 return result 16 17 18 def merge_sort(datalist): 19 length=len(datalist) 20 result=datalist 21 if length>1: 22 left=datalist[0:int(length/2)] 23 right=datalist[int(length/2):length] 24 left=merge_sort(left) 25 right=merge_sort(right) 26 result=merge(left,right) 27 return result
算法分析
首先来分析在合并 (Merge) 过程的所需要的运行时间。
1 C = output[length=n] 2 A = 1st sorted array[n/2] 3 B = 2st sorted array[n/2] 4 i = 1 5 j = 1 6 for k=1 to n 7 if A(i) < B(j) 8 C(k) = A(i) 9 i++ 10 else B(j) < A(i) 11 C(k) = B(j) 12 j++ 13 end
第4和5行分别需要一次操作,整个for循环中,一次循环需要四次操作,假如有m个数那么for循环整个需要4m次操作,那么最后的运行时间为4m+2。因为m总是大于1,所以为了方便计算,假设最后运行时间小于6m。
之后再来看整个算法的运行时间,采用递归树的方法,树的高度为lgn+1,树的每一层运行时间都是6n,总共的运行时间为6nlgn+6n。所以合并排序的时间复杂度为O(nlgn)。