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

本文详细介绍了归并排序算法,这是一种稳定的排序方法,利用完全二叉树的特性提高排序效率。归并排序的基本原理是通过递归或迭代将序列拆分成有序子序列,再合并成整体有序序列。文章提供了递归和迭代两种方式的Python代码实现,并讨论了递归和迭代在性能上的优劣。此外,还提到了归并排序在实际应用中应尽量采用非递归方式以节省空间。
摘要由CSDN通过智能技术生成

一、简介

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

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] 《大话数据结构》


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

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

评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值