归并排序仍然是利用完全二叉树实现,它是建立在归并操作上的一种有效的排序算法,该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列。
基本过程:假设初始序列含有n个记录,则可以看成是n个有序的子序列,每个子序列的长度为1,然后两两归并,得到n/2个长度为2或1的有序子序列,再两两归并,最终得到一个长度为n的有序序列为止,这称为2路归并排序。
下面的截图来自《大话数据结构》相关章节,便于理解整个代码的实现过程。

图中主要表明了实例代码中的两部分,分别为原始序列的拆分和合并两部分。
下面是实例代码:
# -*- coding:utf-8 -*-
__author__ = 'webber'
import random, time
def merge_sort(lst):
if len(lst) <= 1:
return lst # 从递归中返回长度为1的序列
middle = len(lst) / 2
left = merge_sort(lst[:middle]) # 通过不断递归,将原始序列拆分成n个小序列
right = merge_sort(lst[middle:])
return merge(left, right)
def merge(left, right):
i, j = 0, 0
result = []
while i < len(left) and j < len(right): # 比较传入的两个子序列,对两个子序列进行排序
if left[i] <= right[j]:
result.append(left[i])
i += 1
else:
result.append(right[j])
j += 1
result.extend(left[i:]) # 将排好序的子序列合并
result.extend(right[j:])
return result
if __name__ == "__main__":
start = time.clock()
rand_lst = []
for i in range(6):
rand_lst.append(round(random.random()*100, 2))
lst = merge_sort(rand_lst)
end = time.clock()
print lst
print "done ", (end-start)
性能方面:
由于和堆排序类似,都是利用完全二叉树的相关性质,所以它在时间复杂度方面,最好、最坏和平均的时间复杂度都是O(nlogn);但是,在空间复杂度方面,由于它开辟了一块新的内存空间用来存放left和right子序列,而两个子序列的总大小其实和lst是一样的,为n,所以它的空间复杂度为O(n),这是归并排序的主要弱点,牺牲了空间复杂度来换取时间复杂度的减少。稳定性方面,只要在关键码相同时采用左序列元素先行的原则,就能保证算法的稳定性,另一方面,归并排序算法没有适应性,无论对于什么样的序列它都要做logn遍的递归。在《大话数据结构》一书中,对于归并排序,作者提倡尽量考虑非递归的方法(在c中)。
这里记录一下,python有一个模块,专门提供了归并排序的方法,叫做“heapq”模块,因此我们只要将分解后的结果导入该方法即可。例如:
from heapq import merge
def merge_sort(lst):
if len(lst) <= 1:
return lst # 从递归中返回长度为1的序列
middle = len(lst) / 2
left = merge_sort(lst[:middle]) # 通过不断递归,将原始序列拆分成n个小序列
right = merge_sort(lst[middle:])
return list(merge(left, right))
来源:https://www.cnblogs.com/webber1992/p/6142527.html