递归小结

来源:互联网 发布:儿童编程机构加盟 编辑:程序博客网 时间:2024/05/03 02:25
    1.递归的方法能使一些复杂的问题处理起来简单明了,程序短小精悍。但递归也有其致命的缺陷,就是在递归过程中需要不断保存现场,对空间要求很高,容易造成栈溢出,所以递归的深度有限,而且降低了程序的运行效率。因此,在必要的时候应当将递归转化为非递归。
    2.转化的方法一般有以下两种,一是递归转化为递推,用迭代的思想去求解(循环),程序效率要高得多,如求Fabonacci数列问题;二是自己定义堆栈来模拟递归的过程,但会减低程序的可读性,如汉诺塔问题。
    3.程序中存在的单递归和多递归语句分别用单线和树状图分析。
    4.自己了解还不够透彻。如果以后遇到问题,好好研习下此地址。http://blog.163.com/lqp18_31/blog/static/541827692009921115915286/


第一种方法比较简单,下面重点讲一下第二种方法。

设P是一个递归算法,假定P中共有m个值参和局部变量,共有t处递归调用P的语句,则把P改写成一个非递归算法的一般规则为:

1、            1.定义一个栈S,用来保存每次递归调用前值参和局部变量的当前值以及调用后的返回地址。即S应该含有m+1个域,且S的深度必须足够大,使得递归过程中不会发生栈溢出。

       2.定义t+2个语句标号,其中用一个标号标在原算法中的第一条语句上,用另一个标号标在作返回处理的第一条语句上,其余t个标号标在t处递归调用的返回地址,分别标在相应的语句上。

3      3.把每一个递归调用语句改写成如下形式:

(1)                    1. 把值参和局部变量的当前值以及调用后的返回地址压入栈;

(2)                    2. 把值参所对应的实在参数表达式的值赋给值参变量;

(3)                    3. 无条件转向原算法的第一条语句;

4      4.在算法结束前增加返回处理,当栈非空时做:

(1)                     1.出栈;

(2)                     2.把原栈顶中前m个域的值分别赋给各对应的值参和局部变量;

(3)                     3.无条件转向由本次返回地址所指定的位置;

5、    5.增设一个同栈S的元素类型相同的变量,作为进出栈的缓冲变量,对于递归函数,还需要再增设一个保存函数值中间结果的临时变量,用这个变量替换函数体中的所有函数名,待函数结束之前,在把这个变量的值赋给函数名返回。

6、    6. 在原算法的第一条语句之前,增加一条把栈置空的语句。

       7.对于递归函数而言,若某条赋值语句中包含两处或多处递归调用(假设为n处),则应首先把它拆成n条赋值语句,使得每条赋值语句只包含一处递归调用,同时对增加的n-1条赋值语句,要增设n-1个局部变量,然后按以上六条规则转换成非递归函数。

st struct record{ 
     node* a; 
     int state; 
     record(node* a,int state):a(a),state(state){} 
}; 
void non_recursive_inorder(){ 
stack<record> s; 
node* cur=root; //初始化状态 
int state=0; 
while(1){ 
if(!cur){ //如果遇到null结点,返回上一层 
if(cur == root)break;//如果没有上一层,退出循环 
cur=s.top().a; 
state=s.top().state; //返回上层状态 
s.pop(); 
}else if(state == 0){ //状态位0,执行第一个递归inorder(cur->left); 
s.push(record(cur,1));//保存本层状态 
cur=cur->left; //更新到下层状态 
state=0; 
}else if(state == 1){ //状态为1,执行print和inorder(cur->right) 
printf("%d ",cur->x); 
s.push(record(cur,2)); //保存本层状态 
cur=cur->right; //进入下层状态 
state=0; 
}else if(state == 2){ //状态2,函数结束,返回上层状态 
if(cur == root)break; //初始结点的退出状态,遍历结束 
cur=s.top().a; //返回上层状态 
state=s.top().state; 
s.pop(); 


putchar(10); 
}  



0 0
原创粉丝点击