赞
踩
归并排序(Merging Sort)算法是一种稳定排序算法,和堆排序算法一样,都是利用完全二叉树的深度是
⌊
l
o
g
n
⌋
\lfloor logn\rfloor
⌊logn⌋+1 的特性,来提高排序效率,其时间复杂度和堆排序相同,均为O(nlogn)
。
归并排序就是利用归并(将两个或以上的有序表组合成一个新的有序表)的思想实现的排序方法。
基本原理是:假设初设序列有n个记录,则可以看成是n个有序的子序列,每个子序列的长度为1, 然后两两归并,得到 ⌈ n / 2 ⌉ \lceil n/2 \rceil ⌈n/2⌉( ⌈ x ⌉ \lceil x \rceil ⌈x⌉表示不小于x的最小整数)个长度为2或1的有序子序列;再两两归并,……,如此重复,直至得到一个长度为n的有序序列为止,这种方法被称为2路归并排序。
以下面的数组为例,对其使用归并排序算法进行升序排序,整个流程如下面的树状图所示(由于Markdown语法会自动调整子树的位置,因此子树的左右顺序不完全正确),开始递归后,将数组逐渐拆分,直至子序列只有一个元素,然后对有序子序列进行归并,最终合并为一个有序的数组。
901050803070406020
def mergeList(li1, li2): # 合并两个有序数组 li = [] i = 0 j = 0 while i < len(li1) or j < len(li2): if j >= len(li2) or (i < len(li1) and li1[i] <= li2[j]): li.append(li1[i]) i += 1 else: li.append(li2[j]) j += 1 return li def mergeRecursion(li): """ 递归方式实现归并排序,稳定排序 时间复杂度O(n*logn) """ if len(li) <= 1: return li # 将数组划分为左右两部分 mid = (len(li)) // 2 li1 = mergeRecursion(li[:mid]) li2 = mergeRecursion(li[mid:]) return mergeList(li1, li2) if __name__ == '__main__': li = [90, 10, 50, 80, 30, 70, 40, 60, 20] print('归并排序(递归法):', mergeRecursion(li.copy()))
由于上述代码大量使用的递归,代码结构非常清晰,容易理解,但也会造成时间和空间上的性能损耗。通过将递归方式改造为迭代方式,避免了递归时log2n的栈空间,空间复杂度为O(n),避免递归在时间性能上也有一定的提升。
因此使用归并排序时,应尽量使用非递归方式。
下面代码中用到的mergeList
函数,与上述代码中的相同。
def mergePass(li, k): i = 0 lo = [] while i < len(li): # 避免剩余len(li)-x*k(不足k个)元素不参与排序,因此设置条件为只要i<len(li)即不断循环 lo.extend(mergeList(li[i:i+k], li[i+k:i+2*k])) i = i + 2 * k return lo def mergeIteration(li): """ 迭代方式实现归并排序,性能高于递归方式 """ k = 1 n = len(li) while k < n: li = mergePass(li, k) k *= 2 return li if __name__ == '__main__': li = [90, 10, 50, 80, 30, 70, 40, 60, 20] print('归并排序(迭代法):', mergeIteration(li.copy()))
以上,欢迎指正交流~
参考资料:
[1] 《大话数据结构》
[1] 排序算法(一)——冒泡排序算法详解及Python实现
[2] 排序算法(二)——简单选择排序算法详解及Python实现
[3] 排序算法(三)——直接插入排序算法详解及Python实现
[4] 排序算法(四)——希尔排序算法详解及Python实现
[5] 排序算法(五)——堆排序算法详解及Python实现
[6] 排序算法(六)——归并排序算法详解及Python实现
[7] 排序算法(七)——快速排序算法详解及Python实现
赞
踩
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。