Loops 具有两个连续“的转换函数”;“尾巴”;对迭代函数的递归调用

Loops 具有两个连续“的转换函数”;“尾巴”;对迭代函数的递归调用,loops,recursion,stack,iteration,Loops,Recursion,Stack,Iteration,我已经看到了很多关于如何将一个函数在最后一次递归调用转换为迭代版本的例子;但是,如果在末尾有两个递归调用呢 下面是一个Python示例: def doit(x, y, L): if x < y: x += 1 else: x -= 1 y -= 1 if y > 0: L.append(x) doit(x, y, L) doit(x - 1, y - 1, L) #usage L = [] doit(3, 5, L) pr

我已经看到了很多关于如何将一个函数在最后一次递归调用转换为迭代版本的例子;但是,如果在末尾有两个递归调用呢

下面是一个Python示例:

def doit(x, y, L):
  if x < y:
    x += 1
  else:
    x -= 1
    y -= 1
  if y > 0:
    L.append(x)
    doit(x, y, L)
    doit(x - 1, y - 1, L)

#usage
L = []
doit(3, 5, L)
print(L)
def doit(x,y,L):
如果x0:
L.1(x)
doit(x,y,L)
doit(x-1,y-1,L)
#用法
L=[]
doit(3,5,L)
印刷品(L)
请注意,这两个递归调用位于最末尾。不管在这两个递归调用之前我在代码中做了什么,有没有一个通用的方法将这样的东西转换成迭代版本?请记住,我上面提供的只是一个示例。

不,对于这种情况,没有通用且简单的方法,就像对于尾部递归情况一样。即使最后有一个递归调用,但函数不是尾部递归的(例如
return5+foo(x)
),这也是正确的。您必须显式地维护一个堆栈,然后即使在最后有两个以上递归调用的情况下,它也可以工作

要了解原因,请注意尾部递归函数中的每个变量(表示参数和局部变量)在任何给定时刻最多只能有一个可能的值。因此,您永远不需要在RAM中维护它们的多个版本。因为在进行下一个递归调用时,一个好的编译器将销毁它们的当前版本,并在它们当前所在的位置分配新版本。所以它基本上只是修改一个变量,而不是分配新的变量

因此,对于没有“max1version”保证的普通递归函数,在主循环之前声明一个堆栈。其中的每个元素都是所有参数的元组。在循环内部,获取堆栈的最后一个元素(&从堆栈中删除它)。然后简单地在循环中复制/粘贴函数体。然而,除了进行下一个递归调用外,创建一个包含该调用的所有参数值的元素,并将其推送到堆栈上。您的代码已修改:

A = [] #your initial 'L'
stack = [(2,4,A)] #push values of initial call
while stack:
    x,y,L = stack.pop()
    print(x,y)
    if x < y:
        x += 1
    else:
        x -= 1
        y -= 1
    if y > 0:
        L.append(x)
        stack.append((x, y, L))
        stack.append((x - 1, y - 1, L))
A=[]#您的首字母“L”
堆栈=[(2,4,A)]#初始调用的推送值
堆栈时:
x、 y,L=stack.pop()
打印(x,y)
如果x0:
L.1(x)
stack.append((x,y,L))
stack.append((x-1,y-1,L))

然而,只有当递归调用的顺序无关紧要时,his才会工作,比如dfs。否则,我有一个“内部堆栈”的想法,但这个答案已经太长了。

您需要切换stack.append()语句的顺序。这只适用于这个特定的示例,不是一般的解决方案