递归函数难以理解

时间:2013-09-23 01:46:54

标签: recursion

我正在学习数据结构和算法。我发现理解递归特别困难。 所以我有以下问题。但它们与任何特定代码无关。

  1. 当我实现方法时,我应该在何时/何地考虑递归?
  2. 在一般编码约定中,如果它们都可行,我是否应该优先考虑递归而不是简单迭代?
  3. 如何真正理解大多数可能的递归形式,以便在需要时能够想到它们?学习它的最佳方法是什么? (任何相关的书籍或网站?)有任何模式吗?
  4. 我知道如果你发现简单和自然的递归,这个问题可能听起来没有建设性。 但对我而言,它与我的直觉并不一致。我很感激任何帮助。

4 个答案:

答案 0 :(得分:3)

<强> 1

当数据被视为相似时,通常递归的问题解决方案会更小。例如。如果您有一个二叉树,并且想要获得所有叶节点的总和,那么您将sum-tree定义为如果它是叶节点,则它的总和是它的值,如果它不是叶节点则是它两个子树的总和。

这是我的文字的方案实施

(define (sum-tree tree)
  (if (leaf? tree)
      (node-value tree)
      (+ (sum-tree (node-left tree))
         (sum-tree (node-right tree)))))

或者在Java中相同,定义为Node类中的方法。

public int sum()
{
    if ( isLeaf() )
        return value;
    else
        return left.sum() + right.sum();
}

对此的迭代解决方案将更长,更难阅读。在这种情况下,您应该更喜欢递归。

<强> 2

这取决于。如果您使用Python或Java编程,则不应该因为它们没有尾递归。然而,使用Scheme,这是唯一的出路。如果你的语言支持尾递归,你应该在它产生更清晰的代码时选择递归。

第3

边做边学。您需要编写一些使用递归作为工具的算法。如果您不确定流量,请使用纸张跟踪堆栈的流量。学习一些Scheme或类似的函数语言可能会对你有所帮助。

答案 1 :(得分:1)

  1. 当你反复重复同样的事情时,可以使用递归。例如,您正在遍历树,您可以使用递归方法转到左或右子。
  2. 我会选择一个更容易阅读的。通常,简单的迭代会更快,因为它没有任何开销(递归有一些开销,如果级别很深,可能导致堆栈溢出,而简单的迭代则不会)。但是对于某些情况,编写递归函数比在简单迭代中编写等效函数容易得多。
  3. 我宁愿先看问题,然后决定是否需要递归才能解决问题,反之亦然。任何算法书都应该足够好。也许你可以从头开始阅读http://en.wikipedia.org/wiki/Recursion。关于递归有一个简单的例子,我认为你也可以使用简单的迭代来实现它。

答案 2 :(得分:1)

起初,围绕递归缠绕我的头也很难。当我学习递归时,它是在学校期间Java。我发现它经常使用递归而不是迭代器,因为它们很难用Java编写。但是,我学会了Ruby,我发现自己编写的递归方法越来越少了。然后,我学会了ElixirErlang,并发现自己编写了很多递归函数。我的观点?有些工具会以某种风格写作。

现在回答你的问题,因为你刚刚开始学习递归,我建议深入研究它们,并尽量让他们尽可能多地写下它们。

使用递归(例如Fibonacci序列,遍历树等等),某些任务会好得多。其他一些你最好写一个简单的循环。但是,请注意您可以使用循环编写任何递归方法。但在某些情况下可能会变得棘手。

总而言之,一旦掌握了它,递归实际上是一个非常酷的概念。

看一下与递归有关的这个问题:Erlang exercise, creating lists

答案 3 :(得分:1)

我会去研究一些众所周知的递归算法。例如,您可以尝试实现阶乘计算,或者获取树中的所有路径长度。

通过这样做,您(希望)会看到递归方法如何帮助简化代码,以及为什么在这些特定情况下它是一种好方法。这可以为您提供未来应用的一些想法:)