归并排序:
输入:乱序n长数组
输出:排序好的n长数组
时间复杂度:O(nlogn)
空间复杂度:O(n)
我们已经学习了冒泡排序,选择排序与插入排序。深究这几种方法的原理,都是通过反复扫描数组,调整数组内元素的排列顺序来实现的。那么有没有其他思路呢?我们来看归并排序的方法。
其实,就排序本身讲,归并排序并不是效率最好的(其空间复杂度高于后面要讲的快速排序),但是学习归并排序却有着其他更深远的意义:1. 用来初步学习“分治策略”;2. 用来初步学习递归编程
归并排序的思路是这样:将数组尽可能等分成两部分(所谓“尽可能”,就是说偶数时,数组等分;奇数时;长的部分只比短的部分长度大1),然后对这两部分分别再使用归并排序,排序完成后,再合并两个排好序的数组。好了,这当然就是递归。递归原理如下式:
merge_sort(L) = merge(merge_sort(L_left), merge_sort(L_right))
其中, merge_sort表示归并排序,merge表示对两个排好序的数组合并。
通过这里的递归原理,我们发现,归并排序使用的是一种“分而治之”的策略,他是把一个问题(排序一个数组)分解为子问题(排序这个数组的两个子数组),然后再将已经解决的子问题(两个排好序的数组)合并,得到初始问题的结果。这种方法,在算法中,称为“分治策略”。后面会有专题详细讲,这里只是初步了解。
代码由两个函数构成,merge_sort()表述了递归的规则,而merge_sort_helper()的作用在于合并两个排序数组。
需要说明的是,将大问题化成小的子问题解决,再按照一定规则合成原问题的解,这种思路非常重要。分治策略,递归技术,以及更深奥的动态规划基本原理都是这样的。
输入:乱序n长数组
输出:排序好的n长数组
时间复杂度:O(nlogn)
空间复杂度:O(n)
我们已经学习了冒泡排序,选择排序与插入排序。深究这几种方法的原理,都是通过反复扫描数组,调整数组内元素的排列顺序来实现的。那么有没有其他思路呢?我们来看归并排序的方法。
其实,就排序本身讲,归并排序并不是效率最好的(其空间复杂度高于后面要讲的快速排序),但是学习归并排序却有着其他更深远的意义:1. 用来初步学习“分治策略”;2. 用来初步学习递归编程
归并排序的思路是这样:将数组尽可能等分成两部分(所谓“尽可能”,就是说偶数时,数组等分;奇数时;长的部分只比短的部分长度大1),然后对这两部分分别再使用归并排序,排序完成后,再合并两个排好序的数组。好了,这当然就是递归。递归原理如下式:
merge_sort(L) = merge(merge_sort(L_left), merge_sort(L_right))
其中, merge_sort表示归并排序,merge表示对两个排好序的数组合并。
通过这里的递归原理,我们发现,归并排序使用的是一种“分而治之”的策略,他是把一个问题(排序一个数组)分解为子问题(排序这个数组的两个子数组),然后再将已经解决的子问题(两个排好序的数组)合并,得到初始问题的结果。这种方法,在算法中,称为“分治策略”。后面会有专题详细讲,这里只是初步了解。
回到归并排序这个问题,当程序运行起来时,通过对归并排序过程不断推演,会出现数组不断被拆分的现象,如图中分解部分所示:
分解到什么时候会“触底”呢,显然,是当只有一个元素的时候。“触底”后,启动合并,两两间按照合并排序数组的算法合并(具体算法之前有讲,详见:点击打开链接),最终实现排序。
Python 代码如下:
def merge_sort(aList):
n = len(aList)
# 只有一个元素,“触底”了,直接返回
if n <= 1:
return aList
# 分割成两部分
mid = n // 2
left = merge_sort(aList[:mid])
right = merge_sort(aList[mid:])
# 合并
return merge_sort_helper(left, right)
# 这个函数用来合并两个排好序的数组
def merge_sort_helper(l1, l2):
result = []
index1 = index2 = 0
n1 = len(l1)
n2 = len(l2)
while index1 != n1 and index2 != n2:
if l1[index1] < l2[index2]:
result.append(l1[index1])
index1 += 1
else:
result.append(l2[index2])
index2 += 1
result.extend(l2[index2:])
result.extend(l1[index1:])
return result
代码由两个函数构成,merge_sort()表述了递归的规则,而merge_sort_helper()的作用在于合并两个排序数组。
需要说明的是,将大问题化成小的子问题解决,再按照一定规则合成原问题的解,这种思路非常重要。分治策略,递归技术,以及更深奥的动态规划基本原理都是这样的。
1306

被折叠的 条评论
为什么被折叠?



