【问题标题】:what is the benefit of using or creating recursive functions in java?在 java 中使用或创建递归函数有什么好处?
【发布时间】:2016-03-12 11:20:41
【问题描述】:

我想知道在 java 应用程序中使用或创建递归函数可能带来的好处。所以,请告诉我它在哪里有用,我们可以从递归调用中获得好处。但我认为,这需要更多的处理时间那么,为什么我们在 JAVA 应用程序中使用递归调用呢?

【问题讨论】:

标签: java recursion


【解决方案1】:

有时递归可以帮助您设计更简单、更易读的代码。它与递归数据结构(如树)或递归算法特别相关。

优点是您不必在每次迭代时都保留状态。 JVM 以调用堆栈的形式为您完成。

递归的缺点是它需要更多的资源,并且它的深度受到JVM的限制。

【讨论】:

    【解决方案2】:

    使用递归函数只是因为对于许多算法来说,它们是实现它们的自然方式。

    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).

    【讨论】:

      【解决方案3】:

      常见的例子是binary searchquicksort。两者都是divide and conquer algorithms

      如果您不使用递归,您将不得不自己记录外部数据结构(堆栈)。在上述情况下,状态信息保存在调用堆栈中,您不需要额外的管理。所以在某些情况下,它们会导致优雅和高性能的实现。

      【讨论】:

        【解决方案4】:

        当使用递归(例如斐波那契数列)实现时,通常会有看起来更清晰的算法。

        递归非常危险,应该好好测试。在正常应用中,没有理由使用递归,因为它会导致问题。

        【讨论】:

        • 实际上斐波那契是递归的示例。
        【解决方案5】:

        是的,它需要更多的处理时间和更多的内存。但是在某些情况下,递归是最好的方法。
        例如,如果您需要获取目录的完整树并将其存储在某处。您可以编写循环,但这将非常复杂。如果使用递归,它将非常简单。您只会获取根目录的文件,存储它们并为根目录中的每个子目录调用相同的函数。

        【讨论】:

        • 只是想知道 - 你为什么会这么说?递归函数的开销在哪里?毕竟它们只是正常的功能,不是吗?
        • 是的,它们是,但是它们多次调用自己,并且所有调用都保存在内存中,直到最后一次调用返回一个值。
        • 从技术上讲,函数参数保存在所有函数的调用堆栈中。因此递归函数没有特殊的开销。问题在于如何使用它们。
        【解决方案6】:

        递归函数与普通函数没有什么不同!

        与非递归相比,使用递归函数的动机是递归解决方案通常更易于阅读和理解。

        一个例子是斐波那契数函数。

        警告:需要考虑良好的退出条件,否则错误的递归会导致堆栈溢出异常。

        【讨论】:

          【解决方案7】:

          递归是一种简洁而巧妙的方法,可以使方法和函数更短且易于阅读。与其他语言相比,Java 在处理递归方面没有太大区别。

          某些应用程序,如树搜索、目录遍历等非常适合递归。

          缺点是您可能需要一点时间来学习如何使用它,并且您可能需要一点时间来调试错误。如果迭代量很大,递归可能会导致内存问题。

          【讨论】:

            【解决方案8】:

            我只在递归导致代码量大大减少时才使用它。例如,经典的树形分形,您希望通过绘制越来越小的线条来生成一棵树。使用递归,您可以使代码比仅使用循环结构的大多数代码快得多,并且由于每个递归都有局部变量,因此变量更少。但那只是我的个人意见。

            【讨论】:

              猜你喜欢
              • 2013-07-17
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2016-12-19
              • 1970-01-01
              • 2016-02-04
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多