当前位置:   article > 正文

排序算法(六)——归并排序算法详解及Python实现

排序算法(六)——归并排序算法详解及Python实现

一、简介

归并排序(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

10
20
30
40
50
60
70
80
90
90-10-50-80-30-70-40-60-20
90-10-50-80
30-70-40-60-20
90-10
50-80
30-70
40-60-20
60-20
10-90
50-80-
10-50-80-90
30-70-
20-60
20-40-60
20-30-40-60-70
10-20-30-40-50-60-70-80-90

三、代码实现

3.1 递归方式实现归并排序

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()))
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30

3.2 迭代方式实现归并排序

由于上述代码大量使用的递归,代码结构非常清晰,容易理解,但也会造成时间和空间上的性能损耗。通过将递归方式改造为迭代方式,避免了递归时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
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

以上,欢迎指正交流~


参考资料:
[1] 《大话数据结构》


排序算法系列——相关文章

[1] 排序算法(一)——冒泡排序算法详解及Python实现
[2] 排序算法(二)——简单选择排序算法详解及Python实现
[3] 排序算法(三)——直接插入排序算法详解及Python实现
[4] 排序算法(四)——希尔排序算法详解及Python实现
[5] 排序算法(五)——堆排序算法详解及Python实现
[6] 排序算法(六)——归并排序算法详解及Python实现
[7] 排序算法(七)——快速排序算法详解及Python实现

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/一键难忘520/article/detail/919693
推荐阅读
相关标签
  

闽ICP备14008679号