06 | 递归(下):分而治之,从归并排序到MapReduce
黄申
该思维导图由 AI 生成,仅供参考
你好,我是黄申。
上一节,我解释了如何使用递归,来处理迭代法中比较复杂的数值计算。说到这里,你可能会问了,有些迭代法并不是简单的数值计算,而要通过迭代的过程进行一定的操作,过程更加复杂,需要考虑很多中间数据的匹配或者保存。例如我们之前介绍的用二分查找进行数据匹配,或者我们今天将要介绍的归并排序中的数据排序等等。那么,这种情况下,还可以用递归吗?具体又该如何来实现呢?
我们可以先分析一下,这些看似很复杂的问题,是否可以简化为某些更小的、更简单的子问题来解决,这是一般思路。如果可以,那就意味着我们仍然可以使用递归的核心思想,将复杂的问题逐步简化成最基本的情况来求解。因此,今天我会从归并排序开始,延伸到多台机器的并行处理,详细讲讲递归思想在“分而治之”这个领域的应用。
归并排序中的分治思想
首先,我们来看,如何使用递归编程解决数字的排序问题。
对一堆杂乱无序的数字,按照从小到大或者从大到小的规则进行排序,这是计算机领域非常经典,也非常流行的问题。小到 Excel 电子表格,大到搜索引擎,都需要对一堆数字进行排序。因此,计算机领域的前辈们研究排序问题已经很多年了,也提出了许多优秀的算法,比如归并排序、快速排序、堆排序等等。其中,归并排序和快速排序都很好地体现了分治的思想,今天我来说说其中之一的归并排序(merge sort)。
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
- 深入了解
- 翻译
- 解释
- 总结
归并排序算法中的分治思想及递归应用是本文的重点。文章首先深入讲解了归并排序算法的实现过程,强调了分治思想将复杂问题分解为规模相同或类似的子问题,并通过递归不断简化问题的方法。作者还指出了分治思想在分布式系统中的应用,通过将大数据集分解为小数据集并分配到多台机器进行并行处理,最后由中央服务器进行结果合并,以提高处理速度和减少等待时间。文章还介绍了MapReduce框架中的分治思想应用,包括数据分割和映射、归约、合并等步骤。最后,文章总结了递归法的特点和适用场景,以及递归编程在计算机领域的广泛应用。总的来说,本文深入浅出地介绍了递归思想在归并排序和分布式系统中的应用,为读者提供了深入了解递归思想在实际问题中的应用场景和解决方法的内容。
仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《程序员的数学基础课》,新⼈⾸单¥68
《程序员的数学基础课》,新⼈⾸单¥68
立即购买
© 版权归极客邦科技所有,未经许可不得传播售卖。 页面已增加防盗追踪,如有侵权极客邦将依法追究其法律责任。
登录 后留言
全部留言(79)
- 最新
- 精选
- Healtheon老师讲的是最经典的2路归并排序算法,时间复杂度是O(NlogN)。如果将数组分解成更多组(假设分成K组),是K路归并排序算法,当然是可以的,比如K=3时,是3路归并排序,依次类推。3路归并排序是经典的归并排序(路归并排序)的变体,通过递归树方法计算等式T(n)= 3T(n/3)+ O(n)可以得到3路归并排序的时间复杂度为O(NlogN),其中logN以3为底(不方便打出,只能这样描述)。尽管3路合并排序与2路相比,时间复杂度看起来比较少,但实际上花费的时间会变得更高,因为合并功能中的比较次数会增加。类似的问题还有二分查找比三分查找更受欢迎。
作者回复: 很好的回答👍
2018-12-215183 - 大悲思考题: 如果不是分为两组,而是多组是可行的,但是处理起来比较麻烦。虽然分组的时候,能够更快完成,但是在合并的时候需要同时比较多组中的数据,取最小的一个。当分组数量比较大的时候,在合并的时候,为了考虑效率,需要维护一个堆来取最小值。假设分为N组,分组的时间复杂度是logn(N为底), 合并的时候时间复杂度为nlogN,总的时间复杂度不变,还是nlogn。不知道理解对不对,请老师指教!
作者回复: 用堆取最小值,思路不错
2018-12-21233 - swortect老师,如果要排序的数组很大,两个最大的子节点排好序之后,交给最终的机器做最后的排序依然是一堆数据放在一个机器上
作者回复: 这里我有个细节没说清楚,如果数组是有序的,每次只需要从磁盘,有序的取出一部分到内存进行合并
2018-12-24325 - 指间砂的宿命分成超过两个组的更多组是可行的,不过这样在递归调用时一个是有可能产生更多的中间状态数据,再一个在合并阶段,需要比较更多个分组的数据,实际上在最小粒度的时候,比较大小的就是两个数字,即便上层分成多个组,在合并的最底层依旧是从两两之间比较合并的,感觉分成多组的并没有啥优势,还带来了比较处理的复杂性
作者回复: 是的 有读者说可以用堆来取多个组的最小值,虽然可行,但确实比较复杂
2018-12-2113 - 永旭老师,你好 归并排序代码中有非空判断代码 if (a == null) a = new int[0]; if (to_sort == null) return to_sort; 什么情况下会出现数组是null??
作者回复: 在这个例子里不会出现,不过在实际工作中,这个函数可能被其他代码调用,为了保险起见,加一个最基本的非法检测
2019-01-049 - Joe分成多组归并,主要是合并比较会比较麻烦,会在合并时增加复杂度。比如比较2个数大小,只需要1次,而比较3个数大小,最多需要3次。
作者回复: 是的👍
2019-01-088 - 会飞的猪python实现代码: def mergeSort(list): if(len(list)==0): return 0 if(len(list)==1): return list[0] else: listHalfLen=int(len(list)/2) left=mergeSort(list[0:listHalfLen]) right=mergeSort(list[listHalfLen:]) data=merge(left,right) return data def merge(left,right): mid=[] ai=0 bi=0 if(isinstance(left,int)): leftLen=1 left=[left] else: leftLen=len(left) if(isinstance(right,int)): rightLen=1 right=[right] else: rightLen = len(right) while(ai < leftLen and bi < rightLen): if(left[ai]<right[bi]): mid.append(left[ai]) ai+=1 else: mid.append(right[bi]) bi+=1 if(ai< leftLen): newleft=left[ai:] for i in newleft: mid.append(i) else: newright = right[bi:] for i in newright: mid.append(i) return mid list=[3,8,5,9,7,1,10] mergeSort(list) 刚学python,希望大家多多指教
作者回复: 作为初学者,写得很不错👍
2018-12-288 - 叶嘉祺可以用数学方法证明二分归并排序是最优的应该。二分查找是可以证明的。 二分法我是这样证明的: https://ghostbody.github.io/posts/algorithmn/prove-binary-search-is-better/ 对于归并排序我还在思考利用主定理进行证明。 老师可以一起看下怎么证?
作者回复: 第一次看到读者证明二分法是最优的,赞一个。至于归并排序应该是类似的,唯一不同的是,归并的合并过程也有一个复杂度要计算,而不是像比较大小那样O(1)
2019-06-016 - 有品味的混球MapReduce 分割,映射,洗牌,归约这几个步骤没有具体的例子,就感觉不是很明白,希望这几个步骤还是用文章前半部分的排序的例子来分别举例
作者回复: 这个概念涉及了比较多分布式系统的设计,我可以在后面加餐内容放入一些,或者是放到实战篇内容补上
2019-02-1926 - 子非递归层次太多了,堆栈会溢出
作者回复: 是的 需要转换成循环 或者栈的数据结构
2019-01-066
收起评论