说在所有使用递归的地方for
都可以使用循环是正确的吗?如果递归通常较慢,那么在for
循环迭代中使用递归的技术原因是什么?
并且如果总是有可能将递归转换为for
循环,是否有经验法则?
说在所有使用递归的地方for
都可以使用循环是正确的吗?如果递归通常较慢,那么在for
循环迭代中使用递归的技术原因是什么?
并且如果总是有可能将递归转换为for
循环,是否有经验法则?
Answers:
递归通常要慢得多,因为所有函数调用必须存储在堆栈中,以允许返回到调用者函数。在许多情况下,必须分配和复制内存以实现范围隔离。
某些优化(如尾部调用优化)可使递归更快,但并非总是可能的,并且并非所有语言都实现。
使用递归的主要原因是
当然,每个递归都可以建模为一种循环:这就是CPU最终将要做的事情。递归本身更直接地意味着将函数调用和作用域放在堆栈中。但是将递归算法更改为循环算法可能需要大量工作,并且会使代码的可维护性降低:至于每次优化,都应仅在某些分析或证据表明有必要时才尝试使用它。
说在各处使用递归都可以使用for循环是否正确?
是的,因为大多数CPU中的递归都是使用循环和堆栈数据结构建模的。
如果递归通常比较慢,那么使用它的技术原因是什么?
它不是“通常较慢”:递归错误地应用较慢。最重要的是,现代编译器擅长将某些递归转换为循环,而无需询问。
并且如果总是有可能将递归转换为for循环,是否有经验法则?
编写迭代程序,以便在迭代解释时能更好地理解算法;为算法编写递归程序,最好以递归方式进行解释。
例如,经常以递归方式解释搜索二叉树,运行快速排序以及解析许多编程语言中的表达式。这些也是最好的递归编码。另一方面,就阶乘而言,计算阶乘和计算斐波纳契数更容易解释。使用递归对他们来说就像是用大锤乱打苍蝇:这不是一个好主意,即使在大锤它做了很好的工作+。
如果递归通常较慢,那么将其用于循环迭代的技术原因是什么?
因为在某些算法中很难迭代求解。尝试以递归和迭代的方式解决深度优先搜索。您会发现很难用迭代来解决DFS。
可以尝试的另一件好事:尝试编写Merge进行迭代排序。这将花费您很多时间。
说在各处使用递归都可以使用for循环是否正确?
是。这个线程对此有很好的答案。
并且如果总是有可能将递归转换为for循环,是否有经验法则?
相信我。尝试编写自己的版本以迭代解决深度优先搜索。您会注意到一些问题更容易递归解决。
要使用迭代编写等效方法,我们必须显式使用堆栈。迭代版本的解决方案需要堆栈的事实表明该问题非常困难,可以从递归中受益。通常,递归最适合无法使用固定内存量解决的问题,因此在迭代解决时需要堆栈。话虽如此,递归和迭代在遵循不同的模式时可以显示相同的结果。根据情况确定哪种方法更好,最佳实践是根据问题遵循的模式进行选择。
例如,要找到Triangular序列的第n个三角数:1 3 6 10 15…一个使用迭代算法找到第n个三角数的程序:
使用迭代算法:
//Triangular.java
import java.util.*;
class Triangular {
public static int iterativeTriangular(int n) {
int sum = 0;
for (int i = 1; i <= n; i ++)
sum += i;
return sum;
}
public static void main(String args[]) {
Scanner stdin = new Scanner(System.in);
System.out.print("Please enter a number: ");
int n = stdin.nextInt();
System.out.println("The " + n + "-th triangular number is: " +
iterativeTriangular(n));
}
}//enter code here
使用递归算法:
//Triangular.java
import java.util.*;
class Triangular {
public static int recursiveTriangular(int n) {
if (n == 1)
return 1;
return recursiveTriangular(n-1) + n;
}
public static void main(String args[]) {
Scanner stdin = new Scanner(System.in);
System.out.print("Please enter a number: ");
int n = stdin.nextInt();
System.out.println("The " + n + "-th triangular number is: " +
recursiveTriangular(n));
}
}
大多数答案似乎都假定iterative
= for loop
。如果您的for循环不受限制(la C,您可以使用循环计数器执行任何操作),那么这是正确的。如果它是真实的 for
循环(例如,在Python或大多数功能性语言中,您无法手动修改循环计数器),那么它是不正确的。
所有(可计算的)函数都可以递归实现,也可以使用while
循环(或条件跳转,基本上是同一回事)来实现。如果您确实将自己限制为for loops
,则将仅获得这些函数的子集(如果基本操作合理,则为原始递归函数)。当然,这是一个很大的子集,恰好包含您可能在实践中遇到的每个功能。
更重要的是,很多功能非常容易递归实现,而很难以迭代方式实现(手动管理调用堆栈不计算在内)。
是的,说通过Thanakron Tandavas,
当您解决可以通过分治法解决的问题时,递归非常好。
例如:河内塔
我似乎记得我的计算机科学教授曾经说过,所有具有递归解决方案的问题也都具有迭代解决方案。他说,递归解决方案通常较慢,但与迭代解决方案相比,它们更易于推理和编码时,经常使用它们。
但是,对于更高级的递归解决方案,我不认为它总是能够使用简单的for
循环来实现它们。
与纯迭代方法相比,递归+记忆可能会导致更有效的解决方案,例如,请检查以下内容:http : //jsperf.com/fibonacci-memoized-vs-iterative-for-large-n
简短的答案:折衷是递归更快,并且在几乎所有情况下for循环占用更少的内存。但是,通常有一些方法可以更改for循环或递归以使其运行更快
recursion
与iteration
?iteration = for loop
我认为。