算法导论随笔(二): 归并排序与分治策略

在上一篇文章中,我提到了两个排序算法,冒泡排序和归并排序。对于冒泡排序,上一篇文章中已经介绍了它的复杂度为什么是O(n2)。在这一篇文章中,我来写写归并排序的原理以及如何计算它的复杂度。

归并排序(Merge Sort)

首先介绍一下归并排序。归并排序(Merge Sort)是一种经典的排序算法,它的复杂度是O(nlogn)。 对于刚接触算法的同学来说,这个表达式可能比较奇怪。在后文中会介绍它的复杂度为什么是O(nlogn)。

注意: 在算法领域,lognlog2n的缩写,即以2为底n的对数,一定不要混淆。(尤其是数学或其他领域中logn或lgn可能是指以10为底n的对数)

这个算法使用的是分治策略(Divide-and-conquer)。算法分为3个部分,即分解(Divide),解决(Conquer)和合并(Combine)。我们用一个例子来看下。

首先来看分解部分的运行示例图:
在这里插入图片描述
假设我们有8个数字作为输入,那么归并排序的第一步就是把这8个数字平均分成两组,每组4个数字。接着,这两组4个数字又分别被分为2组,每组两个数字。接着继续分组,直到每组只有一个数字。这一部分的目的是将问题尽可能地分解,直到没法再分解为止。此时,由于问题已经被分解为最小,因此每一个问题也最简单,使我们可以在一个单位时间内就解决1个问题。比如图中8个数字被分为8组,由于每一组只有一个数字,所以每组的数字都是排好序的(因为只有1个数字,所以这个数字就是排好序的)。

接下来看解决合并部分。所谓解决,就是把分解后的简单问题求解。而合并,就是已解决的简单问题的解法,通过合并,一步一步得到最初的复杂问题的解法。
在这里插入图片描述
上图中,85和24是两个排好序的数字通过合并和进一步的解决,得到1组2个排好序的数字24和85,类似地63和45也得到45和63。接着这2组2个数字的数组,又被合并和解决得到24,45,63,85这个排好序的数组。而图中右半部分也得到17, 31, 50, 96这4个排好序的数字。最后,两组数字再一次通过合并和解决,得到最后的结果。

归并排序的分析

前文中提到,归并排序算法的复杂度是O(nlogn)。这个结果是怎么计算出来的呢?这里要使用到二叉树的概念。归并排序算法的执行可以用一颗二叉树来表示。首先我们用MERGE_SORT()代表算法的主函数(分解+解决),也就是递归调用的函数;用MERGE()代表合并过程。
程序MERGE_SORT的伪代码如下:
在这里插入图片描述
算法的主要思路就是找到初始数组的中点,然后将数组平均分为两半,再对两个子数组递归调用MERGE_SORT函数。最后再调用MERGE函数来进行合并。我们可以看以下二叉树:
在这里插入图片描述
图中二叉树的每一个节点代表了一次对于MERGE_SORT的递归调用。每个节点(Node)中箭头左侧的数字是调用之前的数组,箭头右侧代表的是调用函数后得到的结果数组。这棵树的根节点(root)代表了第一次对MERGE_SORT的调用;其他每一个节点都代表了一次对MERGE_SORT的递归调用。而叶子(leaf nodes)节点(蓝色的节点)代表了MERGE_SORT的停止点,也代表了解决和MERGE合并的开始。

对于一课有n个叶子节点的完全二叉树,该二叉树的高度(height)为
h e i g h t = l o g ( n ) height = log(n)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值