递归算法探讨

转载 2011年01月17日 13:53:00

递归算法探讨

递归在计算机科学和数学中是一个很重要的工具它在程序设计语言中用来定义句法在数据结构中用来解决表或树形结构的搜索和排序等问题。另外递归在计算方法、运筹学模型、行为策略和图论的研究中都得到了广泛的应用。 

1、 递归的概念

若一个对象部分地包含它自己或用它自己给自己定义则称这个对象是递归的在程序设计中若一个过程直接地或间接地调用自己则称这个过程是递归的过程。在定义一个过程或函数时出现了调用本过程或函数的成分即调用自己本身称之为直接递归若过程或函数P调用过程或函数Q , 而 调用P, 称之为间接递归。对于问题定义是递归的数据结构是递归的问题解法是递归的3种情况都可以采用递归方法来处理。

2、 递归算法的本质

递归算法的本质是把一个大型复杂的问题层层转化为若干与原问题相似的规模较小的问题来处理当规模小到一定程度时可以直接得出它的解这样通过递推就可得到原来问题的解。递归调用的次数必须是有限的必须有递归结束的条件。递归算法的执行过程分为两步第一步是从目标出发追溯到源头称为回溯。第二步是从源头逐步回代达到目标称为递推。由于存在递推在回溯时必须保留其返回的地址与参数使程序能够返回到调用处继续执行这一步是系统通过设置栈来实现的程序设计者无需对栈进行管理

3递归算法的设计

适宜用递归算法求解的问题的充要条件是问题具有某种可借用的类同自身的子问题描述的性质某一有限步的子问题有直接的解存在。递归算法的设计通常有以下个步骤

1分析问题设计递归公式将一个问题化解为一个或多个子问题求解且子问题和原问题具有相同的解法。

2设计递归结束条件控制递归,递归最后一级的调用必须不能再进行递归。 

3确定参数设计递归函数递归过程或递归函数的参数值在递归过程中必须是按规律变化的且参数值的增减方向应与递归终止条件相匹配这样才能控制递归调用。一般递归函数设计的格式为 

if (递归结束条件 

return (结束递归时的返回值)

else

return (递归表达式)

4递归算法的实例

1: 用递归函数编程求的阶乘n!。阶乘函数的递归定义如下: n! =n×(n-1)!  (n> 0)这种定义方法是用阶乘函数自身定义了阶乘函数。由于n!(n-1)!都是同一个问题的求解因此可将n!用递归函数来描述。

程序代码如下

Long f( int n) {

 if ( n = = 0 )

 return 1; //递归的终止条件及相应的操作 

else

 return f (n-1) ; //递归调用 

2: 中序遍历二叉树的递归算法。 

void Inorder ( BTreeNode BT ) {

 if ( BT ! = NULL ) {

 Inorder ( BT - > lchild) ;

 Visit (BT ) ;

 Inorder ( BT - > rchild) ; } } 

5递归算法的执行过程分析

递归的执行依赖系统堆栈的支持递归的执行过程主要分为两步回溯(逐层深入递归调用和递推(层层向上递归返回) , 在回溯时需要做的工作有进行断点保存局部变量、形式参数保存。控制流程转向递归调用的入口。

在本次递归调用结束后向上层调用返回时需要做的工作有保存本次调用的函数结果恢复调用函数时的局部变量和形式参数。根据递归调用时将控制流程转回到调用函数中递归调用的下一行代码处继续执行。

综上所述递归算法的执行过程是不断地自调用直到到达递归出口才结束自调用过程;到达递归出口后,递归算法开始按最后调用的过程最先返回的次序返回;返回到最外层的调用语句时递归算法执行过程结束。

6递归算法的非递归化

递归算法在执行时存在多次进栈和出栈流程的跳转和返回甚至会出现多次重复计算从而影响执行效率。还有一些高级程序设计语言没有提供递归的机制和手段。因此有些时候将递归算法非递归化是有必要的。非递归化最重要的是理解递归的执行过程。对于一般的递归算法,可以利用以下两种方法对其进行非递归化。

1、 尾递归的非递归化

如果递归调用语句是函数的最后一条执行语句,则称这种递归调用为尾递归。当递归调用进入内层时,外层上与各形式参数对应的实际参数值和返回地址都会被编译系统自动保存下来,以备返回时使用。对于尾递归,调用返回时,其后已没有执行语句了。因而外层的实际参数值不会再用到,故没有必要保留。此外由于递归调用语句是最后一条可执行语句,返回地址肯定在函数末尾,故其返回地址也没有必要保留下来。对于这种情况,关键是从递归调用出发,从上而下递归到底找到递归的终止条件然后用循环实现递归算法的非递归化。

3: 的阶乘n!的递归算法的非递归化。

1中给出了求n的阶乘n!的递归算法从上而下递归:

 f(n) = nf(n-1) = n(n-1)f(n-2) = n(n-1) (n- 2) f (n- 3) : : f (0)

 f (0) = 1

设最终结果用f表示由递归的终止条件“n=0结果为1”, f的初始值= 1。由此,可从下而上地用循环实现求f(i),其中i1到任意正整数n,f随着i的变化而变化其非递归算法如下

Long f(int n) {

int i;

long f = 1; 

for( i=1; i<=n; i++) 

f = f*i

return f; } 

类似的情形很多如求2个正整数的最大公约数和求Fibonacci数列等。

2、 非尾递归的非递归化

如果递归调用语句不是函数中的最后一个语句则称该递归调用为非尾递归。对于非尾递归调用中的入口地址计算机隐含地自动设置堆栈保留调用入口地址供递归返回使用。而用非递归方法堆栈是人为设定显现在程序中功能与递归算法相同。

4: 中序遍历二叉树。

由二叉树的递归算法的执行过程知在二叉树非空时首先访问根的左子树再访问根最后访问根的右子树访问根的左子树时先要访问左子树根的左子树再访问左子树的根其次再访问左子树根的右子树⋯⋯如此递归下去一直到树的最左下结点被访问(向左下搜索时将当前结点压入系统栈中保存以便向上回退时调出) , 然后访问最左下结点的父结点通过弹栈获得最左下结点的父结点然后处理该父结点的右子树以此类推循环直到整棵树访问完毕。根据上述对递归执行过程的分析其对应的非递归算法为

void Inorder ( BTreeNode BT ) 

{

if ( ! BT ) return ;

Stack S = Init-Stack () ; 

while ( ! Empty-Stack(S) ) 

 while(BT) //当指针BT非空时入栈 

{Push (S,BT);

   BT = BT-> lchild;} 

Pop(S,BT) ; 

Visit(BT);

BT = BT->rchild; 

//end while (Empty-Stack ( s) ) 

}//end InOrder () 

7结束语

递归算法具有代码简洁思路清晰的优点是设计算法的强有力工具。一般而言递归程序的执行效率低于非递归程序但非递归算法往往难于编写容易出错理论上递归算法都可以转化为非递归算法但存在一些算法很难非递归化如复杂的间接递归因此要根据问题需求及软件和硬件的环境等具体情形选择递归还是非递归。

Android开发艺术探讨精华(完结)

拾起了一年多前看过的一本书,这里记录一些概念,以便以后巩固复习或者面试。 1、configChanges=“orientation|screenSize”,禁止屏幕旋转时重建Activity。...
  • mabeijianxi
  • mabeijianxi
  • 2017年06月16日 13:36
  • 1057

《刀塔传奇》付费设计分析

http://www.gameres.com/msg_252526.html 文/Chevay  QQ:93318228  微博:t.qq.com/Chevay,转载请注明作者和出处 ...
  • kenkao
  • kenkao
  • 2015年09月10日 13:55
  • 1333

有关 Android 应用桌面角标 (BadgeNumber) 实现的探讨

【回复“1024”,送你一个特别推送】 原文作者:小强-贝聊移动 原文地址:http://www.jianshu.com/p/199a9238015f 特别声明:本文为小强-...
  • OQjya206rsQ71
  • OQjya206rsQ71
  • 2017年11月28日 00:00
  • 1079

SSH框架开发中分层意义

在使用SSH框架进行web开发时,进行后端设计时必然会涉及到类的划分,也就会涉及到层次的划分。 所谓层次,也就是一种降低耦合性的措施,人为的通过代码的功能性的不同和调用关系将整个项目的类进行分层...
  • Ldbiy
  • Ldbiy
  • 2014年12月26日 17:08
  • 2000

最大子序列和的探讨

Writted by Bruth_Lee in Southwest universiy of Science and Technology. /** 最大子序列和的探讨 Made by Bruth-...
  • qq_40883132
  • qq_40883132
  • 2017年12月19日 21:49
  • 27

QThread 使用探讨

原文:http://hi.baidu.com/dbzhang800/item/1e931317d37d71dcbe904247 注意:本文停止更新,请优先考虑 Qt 线程基础(QThread...
  • LaineGates
  • LaineGates
  • 2013年08月01日 13:40
  • 1276

Windows服务编写原理及探讨【2】

(二)对服务的深入讨论之上   上一章其实只是概括性的介绍,下面开始才是真正的细节所在。在进入点函数里面要完成ServiceMain的初始化,准确点说是初始化一个SERVICE_TABLE_EN...
  • xl19900502
  • xl19900502
  • 2015年10月14日 22:23
  • 309

游戏服务器架构探讨

有段时间没有研究技术了,这次正好看到了新版的mangos,较之以前我看的版本有了比较大的完善,于是再次浏览了下他的代码,也借此机会整理下我在游戏服务器开发方面的一些心得,与大家探讨。    另外由于...
  • wallwind
  • wallwind
  • 2013年08月23日 16:39
  • 2414

漫谈IA32的系统管理模式(SMM)以及IA32的四种CPU模式

转载: http://bbs.csdn.net/topics/300235884 写在前面   这是我的BIOS启蒙文章第二篇了,上一篇我谈了谈什么是legacy USB,和大家聊了聊在USB键盘背后...
  • gx19862005
  • gx19862005
  • 2015年03月16日 14:26
  • 713

C# Socket网络编程TCP/IP层次模型、端口及报文等探讨

C# Socket网络编程TCP/IP层次模型、端口及报文
  • New_Teacher
  • New_Teacher
  • 2016年04月15日 15:24
  • 561
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:递归算法探讨
举报原因:
原因补充:

(最多只允许输入30个字)