计算机算法基础:13个法则消去递归

基本思路:将递归过程中出现递归调用的地方,用等价的非递归代码来代替,并对return语句做适当处理。
13条规则:处理直接递归调用中的递归代码和return语句,将之转化成等价的迭代代码。
初始

  1. 在开始,插入说明为的代码并将其初始化为空。在一般情况下,这个栈用来存放参数、局部变量和函数的值、每次递归调用的返回地址。
  2. 将标号L1附于第一条可执行语句。然后对于每一处递归调用都用一组下列规则的指令来代替。
    递归调用语句
  3. 将所有参数和局部变量的值存入栈。栈顶指针可作为一个全程变量来看待。
  4. 简历第i个新标号Li,并将i存入栈。这个标号的i值将用来计算返回地址。
    此标号放在规则7所描述的程序段中
  5. 计算这次调用的各实在参数的值,并把这些值赋给相应的形式参数。
  6. 插入一条无条件转向语句转向过程的开始部分:Goto L1
  7. 如果这过程是函数,则对递归过程中含有此次函数调用的那条语句做如下处理:将该语句的此次函数调用部分用从栈顶取回该函数值的代码来代替,其余部分的代码按照原描述方式照抄,并将4中建立的标号附于这条语句上。如果不是函数,也将4中建立的标号附于6所产生的转移语句后面的语句。
    return处理
  8. 如果栈为,则执行正常返回
  9. 否则,将所有输出参数(带有返回值的出口参数,out/inout型)的当前值赋给栈顶上的那些对应的变量。
  10. 如果栈中有返回地址标号的下标,就插入一条此下标 从栈中推出的代码,并把这个下标赋给一个未使用的变量。
  11. 从栈中退出所有局部变量和参数的值并把他们赋给对应的变量。
  12. 如果这个过程是函数,则插入一下命令,这些指令用来计算紧接在return后面的表达式并将结果值存入栈顶。
  13. 用返回地址标号的下标实现对该标号的转向。
    示例
    求数组元素中的最大值
    算法1.10 递归求取数组元素的最大值
    procedure MAX1(i)
    // 查找数组A中最大值元素,并返回该元素的最大下标。//
    global integer n,A(1:n),j,k
    integer i
    if i<n then j←MAX1(i+1) //递归调用//
    if A(i) > A(j) then k←i
    else k←j
    endif
    else k←n
    endif
    return(k) //递归调用的返回//
    end MAX1
    消去上例中的递归:
procedure MAX2(i)
	local integer j,k;global integer n,A(1:n)
	integer I
	integer STACK(1:2*n)
	top<-0		//规则1,声明栈的代码,并初始化为空
L1:if i<n		//规则2,将标号L1赋予第一条可执行代码语句前
	then top<-top+1;STACK(top)<-i;//规则3,参数或局部变量值入栈
	top<-top+1;STACK(top)<-2;//规则4,建立新的标号2,并入栈
	i<-i+1	//规则5,计算参数值
	goto L1	//规则6,无条件转向算法的开始部分
L2:j<-STACK(top);top<-top-1;//规则7,处理函数调用,并将标号2赋于该语句上
	if A(i)>A(j) then k<-I
		else k<-j
	endif
	else k<-n
	endif
	if top=0 then return(k)//规则8,如果栈空,则正常返回
	 else addr<-STACK(top);top<-top-1;//规则10,从栈中退出返回标号
		i<-STACK(top);top<-top-1;//规则11,从栈中退出局部变量和参数的值
		top<-top+1;STACK(top)<-k;//规则12.计算返回值,并将之入栈
		if addr=2 then goto L2 endif//规则12,用返回地址标号的下标实现对该标号的转向
	endif
end MAX2

	
发布了21 篇原创文章 · 获赞 0 · 访问量 333

猜你喜欢

转载自blog.csdn.net/weixin_44225940/article/details/104002402