递归函数和非递归函数的转变
来源:互联网 发布:破解视频聊天软件 编辑:程序博客网 时间:2024/06/03 13:57
原文链接:http://blog.csdn.net/KKevinnHu/article/details/6756200
递归的定义
在定义一个过程或函数时出现调用本过程或本函数的成分,称之为递归。若调用自身,称之为直接递归。若过程或函数p调用过程或函数q,而q又调用p,称之为间接递归。
例 求n!(n为正整数) 。
一般的方法:
n! = 1*2*…*(n-1)*n
递归的方法:
int factorial(int n)
{ int x;
if (n==0)
x=1;
else
x=factorial (n-1)*n;
return(x);
}
在该函数factorial (n)求解过程中,直接调用factorial (n-1)自身,所以它是一个直接递归函数。
递归模型
递归模型是递归算法的抽象,它反映递归问题的递归结构,例如,前面的递归算法对应的递归模型如下:
fun(0)=1 n=0 (1) fun(n)=n*fun(n-1) n>0 (2)
其中:第一个式子给出了递归的终止条件,我们称之为递归出口;第二个式子给出了fun(n)的值与fun(n-1)的值之间的关系,我们称之为递归体。
递归算法到非递归算法的转换
递归算法有两个基本特性:一是递归算法是一种分而治之的、把复杂问题分解为简单问题的求解问题方法,对求解某些复杂问题,递归算法分析问题的方法是十分有效的;二是递归算法的时间/空间效率通常比较差。
因此,对求解某些问题时,我们希望用递归算法分析问题,用非递归算法具体求解问题。这就需要把递归算法转换为非递归算法。
把递归算法转化为非递归算法有如下三种基本方法:
(1)通过分析,跳过分解过程,直接用循环结构的算法实现求值过程。
(2)自己用栈模拟系统的运行时栈,通过分析只保存必须保存的信息,从而用非递归算法替代递归算法。
(3)利用栈保存参数,由于栈的后进先出特性吻合递归算法的执行过程,因而可以用非递归算法替代递归算法。
1、利用循环跳过分解过程从而消除递归
采用循环结构消除递归。求解Fibonacci数列的算法如下:
int Fib(int n)
{ int i,f1,f2,f3;
if (n==1 || n==2) return(n);
f1=1;f2=2;
for (i=3;i<=n;i++)
{ f3=f1+f2;
f1=f2;f2=f3;
}
return(f3);
}
2、模拟系统的运行时栈消除递归
下面讨论直接使用栈保存中间结果,从而将递归算法转化为非递归算法的过程。
仍以例6.1的递归算法进行讨论,其递归模型有一个递归出口和一个递归体两个式子,分别称为(1)式和(2)式。设计一个栈,其结构如下:
struct
{ int vn; /*保存n值*/
int vf; /*保存fun1(n)值*/
int tag; /*标识是否求出fun1(n)值,1:未求出,0:已求出*/
} St[MaxSize]; /*定义栈*/
计算fun1(5)之值的过程如下:
将(5,*,1)进栈;
while (栈不空)
{ if (栈顶元素未计算出栈顶元素的vf值即St[top].tag==1)
{ if (栈顶元素满足(1)式)
求出对应的St[top].vf值,并置St[top].tag=0;
表示已求出对应的函数值;
else /*栈顶元素满足(2)式*/
将(St[top].vn-1,*,1)进栈;
}
else if (栈顶元素已计算出栈顶元素的vf值即St[top].tag==0)
显然栈顶元素由次栈顶元素通过(2)式分解得到的,回过来
由栈顶元素的vf值计算出次栈顶元素的vf值并退栈;
if (栈中只有一个已求出vf值的元素)
退出循环;
}
St[0].vf即为所求的fun1(n)值;
对应的非递归fun1算法如下:
int fun1(int n)
{ top++; /*初值进栈*/
St[top].vn=n; St[top].tag=1;
while (top>-1) /*栈不空时循环*/
{ if (St[top].tag==1) /*未计算出栈顶元素的vf值*/
{ if (St[top].vn==0) /*(1)式*/
{ St[top].vf=1;
St[top].tag=0;
}
else /*(2)式*/
{ top++;
St[top].vn=St[top-1].vn-1; St[top].tag=1;
}
}
else if (St[top].tag==0) /*已计算出vf值*/
{ St[top-1].vf=St[top-1].vn*St[top].vf; /*(2)式*/
St[top-1].tag=0;
top--;
}
/*栈中只有一个已求出vf的元素时退出循环*/
if (top==0 && St[top].tag==0)
break;
}
return(St[top].vf);
}
- 递归函数和非递归函数的转变
- 递归函数和非递归函数的转变
- 递归与非递归的转变
- 组合函数递归和非递归实现
- 递归和非递归实现规律函数
- Fibonacci函数的递归和非递归实现
- 递归函数的非递归化
- 9.栈的应用-递归函数转非递归函数
- 递归函数转换为非递归函数
- ackerman函数的非递归实现(递归函数非递归化)
- 某些函数的递归与非递归实现的比较
- 字符串反序函数的递归与非递归解法
- hanoi塔的递归以及非递归函数
- 一类void 递归函数的非递归实现
- ackman函数的非递归实现
- Ackerman函数的非递归实现.
- 二分查找的递归和非递归实现(C++函数模版)
- 函数的递归和调用
- MSDN的使用及VC6.0的调试
- Python实现各类数据结构和算法---直接选择排序
- 【C解析之六】文件初探
- arcgis server开发的一点浅见
- [2014.3.17]开发板设备驱动程序的Makefile文件
- 递归函数和非递归函数的转变
- Tomcat 系统架构与设计模式,第 2 部分: 设计模式分析
- MFC数据类型汇总及说明
- 基于2.6.35内核的OV9650摄像头驱动分析
- 字符串是否有相同的字母
- SQL Server 触发器
- ubuntu+xplanner-plus
- 网络121第3周实验——实现随机点名的签到程序
- 课程资源收录