归并排序

归并排序:
输入:乱序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()的作用在于合并两个排序数组。
需要说明的是,将大问题化成小的子问题解决,再按照一定规则合成原问题的解,这种思路非常重要。分治策略,递归技术,以及更深奥的动态规划基本原理都是这样的。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值