让我们来看看骑士之旅的问题。可以转换为迭代吗?困扰我的是回溯部分。如何在循环中回溯?当我从递归到迭代时,是否必须使用堆栈数据结构来实现回溯?
我在这里更好地问了这个问题:Can someone describe through code a practical example of backtracking with iteration instead of recursion?
答案 0 :(得分:15)
不,它不可能。
通过使用显式LIFO数据结构“模拟”递归,可以迭代地实现所有递归算法。但这并没有改变算法本身,即算法仍然是递归的,而不是迭代的。
同时,回溯是递归的固有属性。如果你有回溯,你有递归。您可能知道,一类允许直接真正转换为迭代的算法是尾递归算法。但是回溯的存在意味着你的递归不是尾递归。
您可以做的是尝试发明一种不需要回溯的算法。当然,这将是一个完全不同的算法,而不是原始递归算法到迭代形式的转换。
答案 1 :(得分:8)
所有递归算法都可以转换为迭代算法,反之亦然。这是Church-Turing论文的直接结果。
它可能并不总是显而易见(或微不足道),但任何算法都可以表示为递归或迭代过程;对于一般情况,这个问题已被回答before。
对于如何,有几种技术可以应用于从一种风格转到另一种风格,例如看一下this答案,或者更详细一些讨论阅读this文章,该文章解释了如何使用堆栈来消除递归。
答案 2 :(得分:2)
基本上,每个递归都可以实现为循环+堆栈,因为它基本上基本上是在机器(硬件)级别实现的 - 只是一堆分支和用于存储返回地址和参数的堆栈。
在不满足条件的情况下重复循环,而不是递归调用 - 只需将下一次迭代(可能是最后一个状态)的参数推送到堆栈,然后返回循环的起始点
编辑:(因为很明显你在谈论尾递归回溯,而不是一个简单的递归):
来自wikipedia:In computer science, a tail call is a subroutine call that happens inside another procedure as its final action
。据我所知,具有多个递归调用的函数 - 根据定义不是尾递归,并且由于回溯算法确实有多个调用,因此它们不是“尾递归”。
另请注意 - 只有循环和常量空间的程序可以转换为以多项式时间运行的第二个程序P'(因为最多有2^CONST
个状态,基本上是{{1并且验证每一个都是在多项式时间内完成的 - 总共CONST'
时间,这仍然是多项式的,所以除非P=NP
,否则不可能它将允许我们通过将回溯解转换为基于循环的多项式解决多项式时间SAT。 (而且我相信从HP进一步减少是可行的,无论如何都表明它是不可能的。)