《算法基础:打开算法之门》一2.4 递归

本节书摘来自华章出版社《算法基础:打开算法之门》一书中的第2章,第2.4节,作者 [美]托马斯 H 科尔曼(Thomas H Cormen),更多章节内容可以访问云栖社区“华章计算机”公众号查看

2.4 递归

利用递归技术,能将一个问题转化为同一个样子问题的求解过程。这是我最喜欢的经典的递归例子:计算n!(“n的阶乘”),它被定义为如下,对于一个非负数n,当n=0时,n!=1且n!=n(n-1)(n-2)(n-3)…3•2•1(如果n≥1)。例如,5!=5•4•3•2•1=120。22观察得(n-1)!=(n-1)(n-2)(n-3)…3•2•1,并且得n!=n•(n-1)!(对于n≥1)。针对n!这个问题,我们定义了“较小的”问题,也就是(n-1)!。我们能够写出一个递归程序来计算n!,具体如下:

image
image

第2步的表达方式过于啰嗦。我可以将其改写为“Otherwise,return n•FACTORIAL(n-1)”(否则,返回nFACTOR2AL(n-1)),即在一个更大的算术表达式中使用递归调用的返回值。

对于递归,我们必须强调两个特性。首先,必须有一个或多个基础情况(base case),它是指不用递归而直接计算出结果。第二,程序中的每个递归调用一定是通过一系列关于同一问题的子问题的求解而最终迭代到基础情况。对于FACTORIAL程序,当n等于0时,基础情况发生,并且每一个递归调用最终均会将n归约到1。只要初始时n是非负的,递归调用最终均会归约到基础情况。

证明递归算法工作流程的第一步可能让人感觉过于简单。证明的关键是每次递归调用均会产生正确的结果。只要我们愿意相信递归调用确实得到了正确结果,那么证明正确性通常是容易的。如下是我们如何证明FACTORIAL程序返回了正确的结果。很明显,当n=0时,结果返回1,1等价于n!。假定当n≥1时,FACTORIAL(n-1)这个递归调用返回了正确的结果:它返回了(n-1)!。该程序再用n乘以该值,因此计算出了n!这一结果,也就是最后要返回的值。

下面举一个程序,虽然它利用了正确的数学公式计算,但它不是基于子问题求解的递归调用。当n≥0时,确实有n!=(n+1)!/(n+1)。下列递归程序虽然利用了该数学公式,但是未能得出正确的结果(当n≥1时):

image

如果要调用BADFACTORIAL(1),那么它会产生一个递归调用BADFACTORIAL(2),该递归调用会产生一个递归调用BADFACTORIAL(3),等等,这一系列递归调用均不会归约到基础情况(即n=0事件)。如果要用一种实际编程语言来实现该程序并且将该程序运行到一个真正的计算机上,那么你会很快就能看到一条“栈溢出错误”的错误信息。我们通常能将算法表示成一种递归风格的循环方式。如下是一个线性查找算法,它没有使用标记,而是使用递归方式书写的:

image

这里,子问题是在A[i]~A[n]这个子数组中寻找x的问题。基础情况发生在第1步中即当子数组本身是空时,也就是当i>n时。因为每执行一次第3步的递归调用,如果没有第2步中的值返回,i的值就会自增一,那么最后i会大于n,此时我们会执行基础情况。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
你想知道你的GPS是如何在几秒钟内从看起来无数多条可能路径中找到到达目的地的最快捷路径的吗?当你在网上购物时,你的信用卡账号是如何被保护的呢?答案均是算法。本书是关于计算机算法基础的权威指南。在本书中,作者展示了计算机如何通过算法解决问题。 读者将学习到什么是计算机算法,如何描述计算机算法,以及如何评估计算机算法。读者还将学习到在计算机中查找信息的简单方法;在计算机中将信息按照某个预定的顺序重排(“排序”);如何解决那些在计算机中能使用一种被称为“图”的数学结构来建模的基本问题(可用于对道路网建模,针对任务间的依赖建模,以及金融套利交易建模);如何解决关于字符串(例如DNA结构)的问题;密码学的基本原理;数据压缩的基本原理;甚至那些至今还没有人得出如何借助计算机在一段合理的时间内求解的问题。 计算机是如何解决问题的呢?小小的GPS是如何只在几秒钟内就从无数条可能路径中找出到达目的地的最快捷路径的呢?在网上购物时,又如何防止他人窃取你的信用卡账号呢?解决这些问题,以及大量其他问题的答案均是算法。我写本书的目的就是为你打开算法之门,解开算法之谜。 我是《算法导论》的合著者之一。《算法导论》是一本特别好的书(当然,这是我个人的主观评价),但是它确实相当专业。 本书并不是《算法导论》,甚至不能被称为一本教材。它既没有对计算机算法领域进行广度或深度的研究,也没有遵照惯例来讲述设计计算机算法的方法,甚至连一道需要读者自己求解的难题或者练习题也没有。 那么,这是一本什么样的书呢?如果你符合如下条件,那么就可以开始阅读之旅了: ●你对计算机如何解决问题感兴趣; ●你想知道如何评估这些解决方案的质量; ●你想了解计算方面的问题和这些问题的解决方案是如何与非计算机世界关联起来的; ●你能处理一点数学运算; ●你不需要编写过计算机程序(当然,编写过程序更好)。 一些计算机算法方面的书籍是讲述理论概念的,并涉及非常少的技术细节;一些书籍关注的全是技术细节;而另外一些书籍是介于这两者之间的。每类图书都有自己的定位,我将本书定位于介于两者之间。诚然,本书涉及了一些数学知识,并且部分地方阐述得非常仔细,但是我已经竭力避免深入阐述细节(或许除了本书的末尾部分,我无法克制住自己,阐述了一些细节知识)。 我认为本书有点像开胃菜。设想你去了一家意大利餐厅,点了一份开胃菜,直到吃完开胃菜,你才会决定是否点其余食物。开胃菜到了,你就开始用餐了。或许你不喜欢吃开胃菜,并且决定不点其他菜了。可能你喜欢吃开胃菜,但是吃完它,你就感觉饱了,因此不需要点其他菜了。或者也有可能你喜欢吃开胃菜,但你并没有吃饱,此时你便开始期待其他菜了。将本书看作开胃菜,我希望能够产生后两种结果之一:或者读完了本书,你就很满足,感觉没有必要再深入探究算法世界了;或者你非常喜欢从本书中所学到的知识,以至于你想要学习更多算法方面的内容。每一章最后一节的标题为“拓展阅读”,其中会介绍更多关于该章主题的更为深入的书籍和文章。 你将从本书中学到什么: 我无法断定你将从本书中学到什么。如下是我希望你能从本书中学到的: ●什么是计算机算法,能够采用一种方式来描述计算机算法,以及如何评估算法。 ●在计算机中查找信息的简单方式。 ●在计算机中重排信息以使其以一种预定顺序排列的方法。(我们称这一任务为“排序”。) ●如何解决那些能在计算机中以一种称为“图”的数学结构建模的基本难题。在许多应用中,利用图建模的领域包括:道路网(哪些十字路口到哪些十字路口有直接相连的道路,这些道路有多长),任务间的依赖关系(哪个任务必须在其他任务之前完成),金融关系(世界各国货币间的汇率是多少),或者是人与人之间的联系(谁认识谁?谁讨厌谁?哪个演员和哪个演员出现在同一个电影中等)。 ●如何解决关于文本字符串的问题。其中一些问题在某些领域有所应用,例如生物学领域,其中字符表示基本的分子,字符串表示DNA结构。 ●密码学背后的基本原理。即使你自己从来没有加密过一条信息,你的计算机很可能已经对它执行加密操作了(例如当你在网上购物时)。 ●数据压缩的基本概念,这远远超过了“f u cn rd ths u cn gt a gd jb n gd pay”背后的压缩原理。 ●计算机在任意合理的时间内都难以解决的一些问题,或者至少还没有人想出如何解决的问题。 为了理解本书中的内容,你需要事先了解什么 正如我之前所说的,本书中涉及部分数学知识。如果你害怕数学,那么你可以尝试着跳过它,或者你也可以尝试着阅读涉及更少专业技术知识的书籍。但是我已经尽力做到令数学部分变得容易理解了。 我假定你从来没有写过,甚至从来没有读过一个计算机程序。如果你能看懂提纲的内容,就应该能够理解我是如何表达每一步算法,以及如何将这些步骤合并在一起组合成一个完整的算法的。如果你听到过
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值