我需要转换
def aRecursive(n):
if n is 1:
return 3
else:
return 2 * aRecursive(n-1) + 5
进入for循环和while循环。我似乎无法围绕这个过程。这些循环的原始函数是:
a(1) = 3
a(n) = 2 * a(n-1) + 5
答案和解释会有很大帮助。
答案 0 :(得分:1)
我将根据函数的调用方式提供解决方案。此解决方案是通用的,因为您可以使用相同的方法将任何递归函数转换为迭代函数。这在理论上是可行的,但似乎没有人谈论如何。由于您的功能很简单,因此不难想出迭代功能。但是如何对二叉树的非递归后序遍历呢?如果您没有我将要提供的通用方法,您只能根据具体情况进行。
我们走了。首先,我们需要稍微更改您的递归版本以便于转换:
def f(N):
n = N # N is the top level parameter passed to this function
res = None # res is the result returned by this function
[start]: # here we create a label; not python, only for converting
if n == 1:
return 3
else:
return 2 * f(n-1) + 5
接下来我们将转换两件事:函数调用和return语句。函数调用基本上是两步:将参数和返回地址推送到堆栈并跳转到实际代码。 return
基本上是弹出参数并跳转到保存的地址。所以我们走了:
def f(N):
n = N # N is the top level parameter passed to this function
res = None # res is the result returned by this function
[start]: # here we create a label; not python, only for converting
if n == 1:
return 3
else:
push(n) # push current parameter; since there is only one recursive function call in the body, we know where to return and there is no need to push the return address
n = n-1 # the next level actual parameter is now n-1
goto [start] # we go to the code of the function which is the start of this same function
return 2 * f(n-1) + 5 # we will never reach here... this line is where we need to return when any `return` statements is met
接下来,我们将更改第一个return
语句(return 3
):
def f(N):
n = N # N is the top level parameter passed to this function
res = None # res is the result returned by this function
[start]: # here we create a label; not python, only for converting
if n == 1:
res = 3
# for `return` we need to see if this is the top level or a inner recursive call
if stack is empty: # we are in top level
return res
# hey we are in a recursive call, and we need to return to the code after `goto`, why not move these code here?
else:
n = pop() # we pop the parameter saved
# this line is where we need to return when any `return` statements is met
return 2 * f(n-1) + 5
else:
push(n) # push current parameter; since there is only one recursive function call in the body, we know where to return and there is no need to push the return address
n = n-1 # the next level actual parameter is now n-1
goto [start] # we go to the code of the function which is the start of this same function
然后我们将转换return 2*f(n-1)+5
:
def f(N):
n = N # N is the top level parameter passed to this function
res = None # res is the result returned by this function
[start]: # here we create a label; not python, only for converting
if n == 1:
res = 3
if stack is empty:
return res
else:
[loop]:
n = pop() # we pop the parameter saved
# begin conversion of return
res = 2*res+5
if stack is empty:
return res;
else:
# we need to pop stack and jump to the same return, so we just jump to [loop]
goto [loop]
else:
push(n) # push current parameter; since there is only one recursive function call in the body, we know where to return and there is no need to push the return address
n = n-1 # the next level actual parameter is now n-1
goto [start] # we go to the code of the function which is the start of this same function
现在转换完成了,我们需要简化这个混乱。首先,我们应该考虑是否真的需要堆栈。对于这个特殊问题,每次推送只需n=n-1
,每个pop都会生成n=n+1
。所以堆栈并不是真的需要。
def f(N):
n = N # N is the top level parameter passed to this function
res = None # res is the result returned by this function
[start]: # here we create a label; not python, only for converting
if n == 1:
res = 3
if n == N: # SAME as stack is empty
return res # really return
else:
[loop]:
n = n+1 # WE JUST INCREASE N INSTEAD OF POP
res = 2*res+5
if n==N: # SAME as stack is empty
return res;
else:
goto [loop]
else:
# NO PUSH NEEDED
n = n-1 # the next level actual parameter is now n-1
goto [start]
删除了堆栈,我们需要使这些goto
语句消失。请注意[start]
标签和goto [start]
制作循环,我们只需要将它们设为'while'循环:
def f(N):
n = N # N is the top level parameter passed to this function
res = None # res is the result returned by this function
# we reverse the if n==1 and make it a condition in while
while n != 1:
# NO PUSH NEEDED
n = n-1 # the next level actual parameter is now n-1
# you soon noticed the above calculation is not needed at all, it just sets n = 1
res = 3
if n == N:
return res
else:
[loop]:
n = n+1
res = 2*res+5
if n==N:
return res;
else:
goto [loop]
我们优化了第一个循环并将其替换为n=1
。我们需要使[loop]
和goto [loop]
标记的第二个循环消失:
def f(N):
n = N # N is the top level parameter passed to this function
res = None # res is the result returned by this function
n = 1 # the result of the first while loop
res = 3
if n == N:
return res
else:
do: # Python does not have do while, but it is straight forward to do this convert
n = n+1
res = 2*res+5
while n!=N
return res
我们很快就会注意到前4个语句可以合并,我们会删除所有评论:
def f(N):
n = 1
res = 3
if n == N:
return res
else:
do:
n = n+1
res = 2*res+5
while n!=N
return res
我们将撤销if n==N
声明:
def f(N):
n = 1
res = 3
if n != N:
do:
n = n+1
res = 2*res+5
while n!=N
return res
else:
return res
很明显return res
可以置于顶层,if n!=N
和do/while
循环可以合并为一个while
循环:
def f(N):
n = 1
res = 3
while n != N:
n = n+1
res = 2*res+5
return res
这是原始递归函数的等效版本。请注意,我没有深入研究这个特定的问题来提出这个版本,我只处理函数调用转换。我建议你在自己喜欢的文本编辑器中自己完成整个过程,这很有趣。你会发现它是非常机械的,唯一需要考虑的是堆栈的使用。其他技术,如“反向条件”或“转换为结构循环”非常容易。
有趣的是,迭代版本比仅基于转换过程的递归版本更有效,因为:1。我们消除了堆栈的使用; 2.我们消除了一个将n减少到1的循环。我们至少节省了一些CPU周期和堆栈存储。
答案 1 :(得分:0)
一个可能的for
循环:
def a(n):
answer = 3
for i in range(n - 1):
answer = answer * 2 + 5
return answer
可能的while
循环,但我并不特别喜欢在这里使用while
:
def a(n):
answer = 3
while n > 1:
answer = answer * 2 + 5
n -= 1
return answer
请注意,这些答案(或原始代码)都不会处理小于1的n
。
a(1) = 3
a(n) = 2 * a(n - 1) + 5
因此,如果您要计算a(5)
,则有两种合理的方法。一个是写出一些递归的东西:
a(5) = 2 * a(4) + 5
然后计算a(4)
:
a(4) = 2 * a(3) + 5
所以a(5)
现在是:
a(5) = 2 * (2 * a(3) + 5) + 5
您可以继续此过程,直到您不再引用a
为止,然后您就可以进行算术运算。
非递归方式是计算:
a(1) = 3
a(2) = 2 * a(1) + 5 = 2 * 3 + 5 = 11
a(3) = 2 * a(2) + 5 = 2 * 11 + 5 = 27
a(4) = 2 * a(3) + 5 = 2 * 27 + 5 = 59
a(5) = 2 * a(4) + 5 = 2 * 59 + 5 = 123
这样,你从3开始,然后在每一步,乘以2并加5以获得下一个数字。当你到达试图计算函数的n
时,就停止。
第二种(非递归)方法是for
和while
循环上面的工作方式。