以下是本人学习极客时间的专栏《数据结构与算法之美》后,自己动手敲代码实现,并写下当时的思考,希望对你也有帮助。
系列文章:
工作后,为什么还要学习数据结构与算法
Python-排序-冒泡排序-优化
Python-排序-选择排序-优化
Python-排序-插入排序-优化
每当我在编写递归程序的时候,我都能感受到分治算法的强大威力。分治思想,也就是分而治之,将一个复杂的大问题可以分解成若干个子问题,子问题解决后,经过合并,最终得到大问题的解。想想生活中不也到处充满着分治思想吗?
一个大公司会分成若干部门,部分有若干负责人,负责人下面有若干员工。公司运转的好不好,要看部门运转的情况及部门之间的协调效果(归并),一个部门的运转情况要看负责人的规划和实施(对任务的更细分解),负责人的规则和实施又源自于每一个员工的工作绩效。每一个员工都优秀,再加上一级一级的归并,最终会体现在公司的经营业绩上面。
计算机领域中的分治思想的应用更是非常广泛,比如近些年非常火爆的分布式系统架构 Hadoop 中的 MapReduce。无论今后的技术更新迭代速度有多快,但其用到的算法思想,数学原理都是近百年前的东西,因此只要学好基础的算法、计算机相关的一些数学知识,就可以以不变应万变,无论何种新技术,都可以很快掌握。
今天我试着写了分治思想的排序算法–归并排序,它的思路也比较简单,以数组为例,要对一个数组进行排序,可以将数组从中间分成左右两部分,如果左部分有序,右部分也有序,那么就可以按照一定的顺序从左部分和右部分抽取数据组成一个有序的数组,接下来的问题就是如何让左部分和右部分有序,同样的道理,再次进行分解,直到最后的部分只有一个元素为止,再对分解后的部分进行归并,最终完成排序任务。
归并排序的代码比较容易写出来,但如何使用哨兵来优化性能,却需要动一动大脑,我也是考虑了好一会再想出来,今天特意写出来分享一下。
归并排序的思路
-
给定待排序的数组 data_list,长度为 n ,设置首尾两个游标 p,q,初始状态,p = 0,q = n,先不纠结是 n 还是 n-1 。
-
分解: 取中间值 r = (p + q)/2 ,将数组分成左部分 data_list[p,r],右部分 data_list[r+1,q] 。
-
对上述左右部分递归调用分解。
-
归并左部分和右部分的结果。
-
退出条件是 p>=q。
下面直接给出归并排序的 Python 代码,你也可以改写成自己熟悉的编程语言。
归并排序代码(python)
def merge_sort(data_list):
'''
归并排序程序入口
'''
length = len(data_list)
merge_sort_c(data_list,0,length)
def merge_sort_c(data_list,p,q):
'''
递归调用
'''
#退出条件
if p+1>=q:
return
else:
r = (p+q)//2
merge_sort_c(data_list,p,r)
merge_sort_c(data_list,r,q)
merge(data_list,p,r,q) #将data_list[p:r] 与 data_list[r:q] 按顺序归并到 data_list 相应位置
def merge