如果我们使用循环而不是递归,或者反之,在两者都可以达到相同目的的算法中,性能是否会受到影响?检查给定的字符串是否是回文。 我见过许多程序员使用递归作为一种炫耀的手段,当一个简单的迭代算法可以满足要求。 编译器在决定使用什么时起着至关重要的作用吗?
当前回答
迈克说得对。Java编译器或JVM没有优化尾部递归。你总是会得到这样的堆栈溢出:
int count(int i) {
return i >= 100000000 ? i : count(i+1);
}
其他回答
对于可以分解成多个更小的部分的问题,递归比迭代更好。
例如,要制作一个递归斐波那契算法,您将fib(n)分解为fib(n-1)和fib(n-2),并计算这两部分。迭代只允许你一遍又一遍地重复一个函数。
然而,Fibonacci实际上是一个坏例子,我认为迭代实际上更有效。注意fib(n) = fib(n-1) + fib(n-2)和fib(n-1) = fib(n-2) + fib(n-3)。Fib (n-1)被计算了两次!
一个更好的例子是树的递归算法。分析父节点的问题可以分解为分析每个子节点的多个更小的问题。与斐波那契例子不同,较小的问题是相互独立的。
所以,对于那些可以分解成多个、更小、独立、相似问题的问题,递归比迭代更好。
在很多情况下,它提供了比迭代方法更优雅的解决方案,常见的例子是遍历二叉树,所以它不一定更难维护。一般来说,迭代版本通常更快一些(在优化过程中可能会取代递归版本),但递归版本更容易理解和正确实现。
递归有一个缺点,使用递归编写的算法的空间复杂度为O(n)。 而迭代方法的空间复杂度为O(1)。这是使用迭代而不是递归的优点。 那我们为什么要用递归呢?
见下文。
有时使用递归编写算法更容易,而使用迭代编写相同的算法略难。在这种情况下,如果您选择遵循迭代方法,您将不得不自己处理堆栈。
递归?从哪里开始呢,维基会告诉你"这是以一种自相似的方式重复项目的过程"
在我做C语言的时候,c++的递归是上帝的恩赐,就像“尾递归”。您还会发现许多排序算法使用递归。快速排序示例:http://alienryderflex.com/quicksort/
递归就像任何其他算法一样,适用于特定的问题。也许你不能马上或经常找到一个用途,但会有问题,你会很高兴它可用。
在许多情况下,由于缓存提高了性能,递归更快。例如,这是一个使用传统归并例程的归并排序的迭代版本。它将比递归实现运行得慢,因为缓存改进了性能。
迭代实现
public static void sort(Comparable[] a)
{
int N = a.length;
aux = new Comparable[N];
for (int sz = 1; sz < N; sz = sz+sz)
for (int lo = 0; lo < N-sz; lo += sz+sz)
merge(a, lo, lo+sz-1, Math.min(lo+sz+sz-1, N-1));
}
递归实现
private static void sort(Comparable[] a, Comparable[] aux, int lo, int hi)
{
if (hi <= lo) return;
int mid = lo + (hi - lo) / 2;
sort(a, aux, lo, mid);
sort(a, aux, mid+1, hi);
merge(a, aux, lo, mid, hi);
}
PS -这是Kevin Wayne教授(普林斯顿大学)在Coursera上的算法课程上讲的。