【发布时间】:2016-03-12 11:20:41
【问题描述】:
我想知道在 java 应用程序中使用或创建递归函数可能带来的好处。所以,请告诉我它在哪里有用,我们可以从递归调用中获得好处。但我认为,这需要更多的处理时间那么,为什么我们在 JAVA 应用程序中使用递归调用呢?
【问题讨论】:
我想知道在 java 应用程序中使用或创建递归函数可能带来的好处。所以,请告诉我它在哪里有用,我们可以从递归调用中获得好处。但我认为,这需要更多的处理时间那么,为什么我们在 JAVA 应用程序中使用递归调用呢?
【问题讨论】:
有时递归可以帮助您设计更简单、更易读的代码。它与递归数据结构(如树)或递归算法特别相关。
优点是您不必在每次迭代时都保留状态。 JVM 以调用堆栈的形式为您完成。
递归的缺点是它需要更多的资源,并且它的深度受到JVM的限制。
【讨论】:
使用递归函数只是因为对于许多算法来说,它们是实现它们的自然方式。
factorial() 函数就是一个很好的例子:
function factorial(n) {
if (n <= 1) {
return 1; // terminates the recursion
} else {
return n * factorial(n - 1);
}
}
在许多情况下,如果递归调用是函数执行的最后一个操作(“尾递归”),那么可以很容易地使用迭代函数。上面的factorial()函数可以这样写:
function factorial(n) {
var f = 1;
for (var i = 2; i < n; ++i) {
f *= i;
}
return f;
}
递归函数的性能一般不会比迭代函数差,除非递归调用树非线性增长。
斐波那契数列就是一个例子 - f(n) = f(n - 1) + f(n - 2)。
function fib(n) {
if (n <= 2) {
return 1;
} else {
return fib(n - 1) + fib(n - 2);
}
}
由于它在每次调用函数时递归两次,它不如简单地从 1 迭代到 n 高效 - 递归版本至少具有复杂性 O(2^n) 而迭代版本是O(n).
【讨论】:
常见的例子是binary search 和quicksort。两者都是divide and conquer algorithms。
如果您不使用递归,您将不得不自己记录外部数据结构(堆栈)。在上述情况下,状态信息保存在调用堆栈中,您不需要额外的管理。所以在某些情况下,它们会导致优雅和高性能的实现。
【讨论】:
当使用递归(例如斐波那契数列)实现时,通常会有看起来更清晰的算法。
递归非常危险,应该好好测试。在正常应用中,没有理由使用递归,因为它会导致问题。
【讨论】:
是的,它需要更多的处理时间和更多的内存。但是在某些情况下,递归是最好的方法。
例如,如果您需要获取目录的完整树并将其存储在某处。您可以编写循环,但这将非常复杂。如果使用递归,它将非常简单。您只会获取根目录的文件,存储它们并为根目录中的每个子目录调用相同的函数。
【讨论】:
递归函数与普通函数没有什么不同!
与非递归相比,使用递归函数的动机是递归解决方案通常更易于阅读和理解。
一个例子是斐波那契数函数。
警告:需要考虑良好的退出条件,否则错误的递归会导致堆栈溢出异常。
【讨论】:
递归是一种简洁而巧妙的方法,可以使方法和函数更短且易于阅读。与其他语言相比,Java 在处理递归方面没有太大区别。
某些应用程序,如树搜索、目录遍历等非常适合递归。
缺点是您可能需要一点时间来学习如何使用它,并且您可能需要一点时间来调试错误。如果迭代量很大,递归可能会导致内存问题。
【讨论】:
我只在递归导致代码量大大减少时才使用它。例如,经典的树形分形,您希望通过绘制越来越小的线条来生成一棵树。使用递归,您可以使代码比仅使用循环结构的大多数代码快得多,并且由于每个递归都有局部变量,因此变量更少。但那只是我的个人意见。
【讨论】: