|
|
|
|
移动端

问与答

《算法精解:C语言描述》第3章 递归,本章介绍递归,这是一种在许多数据结构和算法中都会用到的技术。本节为大家介绍问与答。

作者:肖翔/陈舸 译来源:机械工业出版社|2012-12-06 10:20

有奖调研 | 1TB硬盘等你拿 AI+区块链的发展趋势及应用调研


问与答

问:下面的递归定义有一个错误。请指出错误并想想该如何修正。给定一个正整数n,其正确的定义通常用来计算分治算法的运行时间,比如归并排序(见第12章)。归并排序将一组数据一分为二,然后分别将两份数据各自再进行分半处理,一直持续这个过程直到每一份都只含一个元素。然后在回归过程中完成各份数据的合并最终产生一个有序的集合。

 
答:该定义的问题在于当n的初始值大于0时将永远无法满足终止条件n=0。为了解决问题,需要一个满足要求的终止条件。n-1这个条件就能很好满足,这意味着也要修改函数中的第二个条件。合适的递归定义应该是这样的:
 

这恰好是归并排序运行时间的正确定义形式。这样一种函数称为递推。在更正式的分析中,递推常用来描述递归算法的运行时间。

问:以递归的思想描述一种求解整数质因子的方法。分析该方法是否是尾递归的并解释原因。

答:递归是一种求解整数质因子的很自然的方法,因为因子分解无非就是不断地解决同样的问题。每当确定了一个因子,剩余因子的集合就变得越来越小。针对这个问题的递归方法可以定义为如下式子:

 
这个定义的意思是说:为了递归地确定整数n的质因子,先确定它的最小质因子i并把它记录到集合P中,然后对整数n=n/i重复这个过程直到n本身成为质数为止,这就是终止条件。这个定义是尾递归的,因为在回归过程中不需要做任何处理,如图3-6所示。
 
图3-6:以尾递归的方式计算整数2409的质因子

问:思考当执行递归函数时栈的使用情况,当递归过程的递推阶段永远不会终止时会出现什么情况?也许如同第一个问题中那样,终止条件永远也无法满足。

答:如果递归函数的终止条件永远得不到满足,最终栈的增长会超过可接受的值,程序会因为栈溢出而终止运行。当程序执行时,一个称为帧指针的特殊指针会寻址栈顶的帧。正是栈指针指向实际的栈顶(即,下一个栈帧将被压入的位置。因此,虽然某个系统可能使用来判断栈溢出,但是它可能是通常会使用的栈指针。)

问:递归函数常常能够以简洁而精确的方式描述计算问题。请描述下面的递归定义式所要表达的计算是什么:

 

答:这个递归定义计算称为调和级数的数列之和。对于给定的正整数n,该函数计算出到第n个调和数。(计算过程与下面给出的调和级数序列是相反的,但下面的方式更好看一些)

 

问:上一个问题中的函数是尾递归的吗?如果是,请解释原因。如果不是,解释原因并给出一个尾递归的版本。

答:上一个问题中定义的函数不是尾递归的。因为递归调用的返回值在一个表达式中使用。这个表达式称为当前调用的返回值。因此,每一个栈帧都必须保留在栈上直到下一个子调用得到它的返回值为止。为了使这个函数成为尾递归,可以利用本章前面提到的以尾递归方式计算阶乘的方法来处理。增加一个参数a来记录当前递归中到目前为止已计算的数列之和。最终,上一个问题的尾递归版本可以表示成:

 


【责任编辑:book TEL:(010)68476606】

回书目   上一节   下一节
点赞 0
分享:
大家都在看
猜你喜欢

读 书 +更多

Visual C++编程从基础到实践

Visual C++ 6.0是Microsoft公司的Visual Studio开发组件中最强大的编程工具,利用它可以开发出高性能的应用程序。本书由浅入深,从基础到实...

订阅51CTO邮刊

点击这里查看样刊

订阅51CTO邮刊