reddit上的一个帖子提出了一个很有趣的问题:

尾递归函数可以简单地转换为迭代函数。其他的可以通过使用显式堆栈进行转换。每个递归都能转化为迭代吗?

文章中的(counter?)例子是:

(define (num-ways x y)
  (case ((= x 0) 1)
        ((= y 0) 1)
        (num-ways2 x y) ))

(define (num-ways2 x y)
  (+ (num-ways (- x 1) y)
     (num-ways x (- y 1))

当前回答

消除递归是一个复杂的问题,在定义良好的情况下是可行的。

以下是简单的情况:

尾递归 直接线性递归

其他回答

这是一个迭代算法:

def howmany(x,y)
  a = {}
  for n in (0..x+y)
    for m in (0..n)
      a[[m,n-m]] = if m==0 or n-m==0 then 1 else a[[m-1,n-m]] + a[[m,n-m-1]] end
    end
  end
  return a[[x,y]]
end

有时候替换递归要简单得多。在20世纪90年代,递归曾经是计算机科学中很流行的东西,所以当时很多普通的开发人员认为,如果你用递归来解决问题,这是一个更好的解决方案。所以他们会使用递归而不是反向循环,或者类似的愚蠢的东西。所以有时候移除递归是一种简单的“这很明显”的练习。

现在这已经不是什么问题了,因为时尚已经转向了其他技术。

看看维基百科上的以下条目,你可以把它们作为一个起点,找到你问题的完整答案。

计算机科学中的递归 递归关系

下面一段话可能会给你一些提示,让你知道从哪里开始:

求解递归关系意味着获得一个封闭形式的解:n的非递归函数。

再看看这篇文章的最后一段。

是否总是可以为每个递归函数编写非递归形式?

是的。一个简单的形式证明是,微递归和非递归演算(如GOTO)都是图灵完备的。由于所有的图灵完备演算在表达能力上是严格等价的,所以所有的递归函数都可以用非递归图灵完备演算来实现。

不幸的是,我无法在网上找到一个好的,正式的GOTO定义,所以这里有一个:

GOTO程序是在寄存器机器上执行的命令序列P,这样P是以下其中之一:

HALT,停止执行 R = R + 1,其中R是任意寄存器 R = R - 1,其中R是任意寄存器 GOTO x,其中x是一个标签 IF r≠0 GOTO x,其中r是任意寄存器,x是一个标签 一个标签,后面跟着上面的任何命令。

然而,递归函数和非递归函数之间的转换并不总是简单的(除非手动重新实现调用堆栈)。

欲了解更多信息,请参阅这个答案。

原则上,在数据结构和调用堆栈都具有无限状态的语言中,总是可以删除递归并替换为迭代。这是丘奇-图灵论文的一个基本结论。

Given an actual programming language, the answer is not as obvious. The problem is that it is quite possible to have a language where the amount of memory that can be allocated in the program is limited but where the amount of call stack that can be used is unbounded (32-bit C where the address of stack variables is not accessible). In this case, recursion is more powerful simply because it has more memory it can use; there is not enough explicitly allocatable memory to emulate the call stack. For a detailed discussion on this, see this discussion.