【发布时间】:2016-11-28 18:54:20
【问题描述】:
几天前我开始阅读这本书Systematic Program Design: From Clarity to Efficiency。第 4 章讨论了将任何递归算法转换为其对应迭代的系统方法。看起来这是一个非常强大的通用方法,但我很难理解它是如何工作的。
在阅读了几篇关于使用自定义堆栈进行递归删除的文章后,感觉这种提议的方法会产生更具可读性、优化和紧凑的输出。
Python 中我想应用该方法的递归算法
#NS: lcs and knap are using implicit variables (i.e.: defined globally), so they won't
#work directly
# n>=0
def fac(n):
if n==0:
return 1
else:
return n*fac(n-1)
# n>=0
def fib(n):
if n==0:
return 0
elif n==1:
return 1
else:
return fib(n-1)+fib(n-2)
# k>=0, k<=n
def bin(n,k):
if k==0 or k==n:
return 1
else:
return bin(n-1,k-1)+bin(n-1,k)
# i>=0, j>=0
def lcs(i,j):
if i==0 or j==0:
return 0
elif x[i]==y[j]:
return lcs(i-1,j-1)+1
else:
return max(lcs(i,j-1),lcs(i-1,j))
# i>=0, u>=0, for all i in 0..n-1 w[i]>0
def knap(i,u):
if i==0 or u==0:
return 0
elif w[i]>u:
return knap(i-1,u)
else:
return max(v[i]+knap(i-1,u-w[i]), knap(i-1,u))
# i>=0, n>=0
def ack(i,n):
if i==0:
return n+1
elif n==0:
return ack(i-1,1)
else:
return ack(i-1,ack(i,n-1))
Step Iterate:确定最小增量,将递归转化为迭代
本书第 4.2.1 节讨论了确定适当的增量:
1) All possible recursive calls
fact(n) => {n-1}
fib(n) => {fib(n-1), fib(n-2)}
bin(n,k) => {bin(n-1,k-1),bin(n-1,k)}
lcs(i,j) => {lcs(i-1,j-1),lcs(i,j-1),lcs(i-1,j)}
knap(i,u) => {knap(i-1,u),knap(i-1,u-w[i])}
ack(i,n) => {ack(i-1,1),ack(i-1,ack(i,n-1)), ack(i,n-1)}
2) Decrement operation
fact(n) => n-1
fib(n) => n-1
bin(n,k) => [n-1,k]
lcs(i,j) => [i-1,j]
knap(i,u) => [i-1,u]
ack(i,n) => [i,n-1]
3) Minimum increment operation
fact(n) => next(n) = n+1
fib(n) => next(n) = n+1
bin(n,k) => next(n,k) = [n+1,k]
lcs(i,j) => next(i,j) = [i+1,j]
knap(i,u) => next(i,u) = [i+1,u]
ack(i,n) => next(i,n) = [i,n+1]
第 4.2.2 节讨论形成优化程序:
Recursive
---------
def fExtOpt(x):
if base_cond(x) then fExt0(x ) -- Base case
else let rExt := fExtOpt(prev(x)) in -- Recursion
f Ext’(prev(x),rExt) -- Incremental computation
Iterative
---------
def fExtOpt(x):
if base_cond(x): return fExt0(x) -- Base case
x1 := init_arg; rExt := fExt0(x1) -- Initialization
while x1 != x: -- Iteration
x1 := next(x1); rExt := fExt’(prev(x1),rExt) -- Incremental comp
return rExt
如何在 Python 中创建{fibExtOpt,binExtOpt,lcsExtOpt,knapExtOpt,ackExtOpt}?
有关此主题的其他材料可以在该方法的主要作者Y. Annie Liu, Professor 的the papers 之一中找到。
【问题讨论】:
-
这是关于这个主题的另一个更普遍的问题:stackoverflow.com/questions/159590/…。如果您在反递归某些代码方面需要一些帮助,请将其发布,以便我们更有效地为您提供帮助。
-
那你问什么?发布一些代码,以便我们为您提供建议。由于帧对象的 cPython 实现,通常在 Python 中递归比正常循环慢。
-
@HolyDanna 我将编辑我的问题以添加我正在使用的一组简单的朴素递归算法,以了解 book 的方法,而不是像上面提到的那样使用自定义堆栈在您的链接中。
-
在我看来,没有得到认可和没有回应是因为这还不是一个独立的问题。为了比较,我们可以很容易地在网上找到阿克曼函数、二项式函数和其他参考的参考资料。我们不能轻易找到的是第 4.3 节。目前,您的听众仅限于阅读并理解第 4 章并愿意为您提供相关教程的人。教程一般超出了 SO 的范围。