浅谈递归向非递归转换方法

  • 格式:doc
  • 大小:36.00 KB
  • 文档页数:5

谈递归向非递归的转换方法
摘要:很多数据结构的定义都是根据递归性质来进行定义的,是因为这些结构固有的性质。

递归算法实际上是一种分而治之的方法,它把复杂问题分解为简单问题来求解。

对于某些复杂问题(例如hanio塔问题),递归算法是一种自然且合乎逻辑的解决问题的方式,但是递归算法的执行效率通常比较差。

因此,在求解某些问题时,常采用递归算法来分析问题,用非递归算法来求解问题;另外,有些程序设计语言不支持递归,这就需要把递归算法转换为非递归算法。

关键词:递归非递归堆栈
一、递归算法
1.递归的定义
递归做为一种算法在程序设计语言中广泛应用。

是指函数/过程/子程序在运行过程中直接或间接调用自身而产生的重入现象。

递归是计算机科学的一个重要概念,递归的方法是程序设计中有效的方法,采用递归编写程序能使程序变得简洁和清晰。

2.引入非递归
从用户使用角度来说,递归真的很简便,对程序宏观上容易理解。

递归程序的时间复杂度虽然可以根据T(n)=T(n-1)*f(n)递归求出,其中f(n)是递归式的执行时间复杂度,一般来说,时间复杂度和对应的非
递归差不多,但是递归的效率是相当低的它主要发费在反复的进栈出栈,各种中断等机制上(具体的可
以参考操作系统)更有甚者,在递归求解过程中,某些解会重复的求好几次,这是不能容忍的,这些也
是引入非递归机制的原因之一。

二、非递归算法
非递归(用栈),也用到栈函数了,和递归就没多大区别了!每次递归进栈出栈,非递归(用栈)的每次调用栈函数也是进栈出栈。

主要是在非递归(用栈)中,它的栈函数里比递归多了些赋值语句,所以效率上,非递归(用栈)比递归差。

只不过,递归越深,占用栈空间越多。

非递归(用栈),占用的栈空间少。

如果,递归的深度还没达到超出栈空间的程度,那么递归比非递归(用栈)好。

如果是非递归(不用栈),当然是非递归最好。

三、递归转非递归的两种方法
将递归算法转换为非递归算法有两种方法,一种是直接求值,不需要回溯;另一种是不能直接求值,需要回溯。

前者使用一些变量保存中间结果,称为直接转换法;后者使用栈保存中间结果,称为间接转换法,下面分别讨论这两种方法。

1.直接转换法
直接转换法通常用来消除尾递归和单向递归,将递归结构用循环结构来替代。

尾递归是指在递归算法中,递归调用语句只有一个,而且是处在算法的最后。

例如求阶乘的递归算法:
long fact(int n)
{
if (n==0) return 1;
else return n*fact(n-1);
}
当递归调用返回时,是返回到上一层递归调用的下一条语句,而这个返回位置正好是算法的结束处,所以,不必利用栈来保存返回信息。

对于尾递归形式的递归算法,可以利用循环结构来替代。

例如求阶乘的递归算法可以写成如下循环结构的非递归算法:
long fact(int n)
{
int s=0;
for (int i=1; i<=n;i++)
s=s*i; //用s保存中间结果
return s;
}
单向递归是指递归算法中虽然有多处递归调用语句,但各递归调用语句的参数之间没有关系,并且这些递归调用语句都处在递归算法的最后。

显然,尾递归是单向递归的特例。

例如求斐波那契数列的递归算法如下:
int f(int n)
{
if (n= =1 | | n= =0) return 1;
else return f(n-1)+f(n-2);
}
对于单向递归,可以设置一些变量保存中间结构,将递归结构用循环结构来替代。

例如求斐波那契数列的算法中用s1和s2保存中间的计算结果,非递归函数如下:int f(int n)
{
int i, s;
int s1=1, s2=1;
for (i=3; i<=n; ++i)
{
s=s1+s2;
s2=s1; // 保存f(n-2)的值
s1=s; //保存f(n-1)的值
}
return s;
}
2. 间接转换法
该方法使用栈保存中间结果,一般需根据递归函数在执行过程中栈的变化得到。

其一般过程如下:
将初始状态s0进栈
while (栈不为空)
{
退栈,将栈顶元素赋给s;
if (s是要找的结果) 返回;
else
{
寻找到s的相关状态s1;
将s1进栈
} }
间接转换法在数据结构中有较多实例,如二叉树遍历算法的非递归实现、图的深度优先遍历算法的非递归实现等等。

使用非递归方式实现递归问题的算法程序,不仅可以节省存储空间,而且可以极大地提高算法程序的执行效率。

本文将递归问题分成简单递归问题和复杂递归问题;简单递归问题的非递归实现采用递推技术加以求解,复杂递归问题则根据问题求解的特点采用两类非递归实现算法,使用栈加以实现。

四.总结
递归算法的优缺点
优点:结构清晰,可读性强,而且容易用数学归纳法来证明算法的正确性,因此它为设计算法、调试程序带来很大的方便。

缺点:递归算法的运行效率较低,无论是耗费的计算时间还是占用的储存空间都比非递归算法要多。

仅仅是机械地模拟还不能达到减少计算时间和存储空间的目的。

因此,还需要根据具体程序和特点对递归调用的工作栈进行简化,尽量减少栈的操作,压缩栈存储以
达到节省计算时间和存储空间的目的。

[参考文献]
[1] 汤卫东; 计算机系统如何将递归算法转化为非递归算法
[2][原创]浅谈递归机制和非递归转换,2007-10-7 编程论坛首发。