迭代(iteration)和递归(recursion)有何区别,为什么或者何时使用一种更好:
while (true) {
// Iterating
}
并且
private void recursion() {
if (true)
recursion(); // Recursing
return;
}
我看到很多使用递归
实现的代码,而这些代码其实可以用一个简单的循环来实现。
迭代(iteration)和递归(recursion)有何区别,为什么或者何时使用一种更好:
while (true) {
// Iterating
}
并且
private void recursion() {
if (true)
recursion(); // Recursing
return;
}
我看到很多使用递归
实现的代码,而这些代码其实可以用一个简单的循环来实现。
public static long fib(long n) {
if (n <= 1) return n;
else return fib(n-1) + fib(n-2);
}
对比
if ((n == 1) || (n == 2)) {
return 1;
} else {
long prev = 1, current = 1, next = 0;
for (long i = 3; i <= n; i++) {
next = prev + current;
prev = current;
current = next;
}
return next;
}
来源:
http://www.csd.uwo.ca/Courses/CS1027a/code/FibonacciDemo.java
fib(n-1) + fib(n-2)
可能非常昂贵,但可以通过一个尾调用辅助函数来实现,该函数接受前两个值作为输入。 - Sideshowcoderreturn recurse(arg)
这样的行,其他算法可以轻松重写以使用此形式。这样做时,返回路径只是爬升堆栈每次返回。您可以通过仅对第一个函数调用不使用堆栈 - 立即返回并且不为每个递归使用任何额外的内存来优化此过程。 - lodn * (n-1)!
,因此递归使用它是有意义的。理论上,您总是可以在迭代和递归之间进行切换。然而,在C/C++/C#/Java的情况下,编译器为您提供了一些支持,这可能会使解决方案更加优雅,特别是当您不知道循环次数时。
最好的例子是列出文件夹及其子文件夹中的所有文件。如果有几个包含子文件夹的子文件夹,则通常在迭代模式下,您需要一个堆栈来保存所有需要分析的文件夹。在递归方法的情况下,堆栈已经由编译器提供,解决方案更加优雅。
递归和迭代是思考解决方案的不同方式。在完整范围内深入解释这两者的区别可能会有些困难。在您的示例代码中,您已经展示了它们之间的差异。
递归函数是调用自身的函数,而迭代函数则是循环执行某个代码块。以下是一些文章,可以帮助您更好地理解它们:
它们可以交替使用来解决不同的问题。本质上,您可以将递归函数迭代地编写,反之亦然。
迭代可能会提高程序的性能。而递归可能会给出更直观和优雅的结果。您可以根据自己的偏好选择其中任何一种!
递归函数通过调用自身的过程工作,直到满足条件,而迭代则使用循环控制结构(例如while、do while、for)以重复一段代码,直到满足某个条件为止。
递归示例:
int rec_func(int u, int k) {
if (k == 0)
return u;
return rec_func(u * k, k - 1);
}
int ite_func(int u, int k) {
while (k != 0) {
u = u * k;
k = k - 1;
}
return u;
}
在我看来,它们之间唯一真正的区别是编译差异。
递归
迭代
数据取自这里。