我试图理解递归是如何工作的。我得到了基本的想法,但细节仍不清楚。这是javascript中的一个简单示例:

function sumTo(n){
    if (n > 1){
        return n + sumTo(n-1)
    } else {
        return n
    }
}

sumTo(3);

它应该计算 3 中的所有数字,结果是 6 (1 + 2 + 3 = 6),但我不明白它是如何工作的。

好的,我们从 if 条件开始。 3 > 1,所以我们返回 n 并再次调用该函数,但是如果括号里面是什么?

它看起来像这样吗:

3 + sumTo(2)//3 - 1 = 2

或者我们不对 n 做任何事情,等待下一个函数:

3 + sumTo(n - 1)//n 稍后会出现

有人告诉我最后一个函数将返回 1 给上一个函数,但我不知道它会用这个 1 做什么。

如果有一些终极假人的分步解释,请分享。

我知道有很多类似的问题,但没有找到帮助。

UPD: 看来我终于找到了它的工作原理,花了两天时间并询问了所有我能问到的人。我会尽力为像我这样的终极傻瓜解释一下。这会很长,但我希望有同样问题的人会找到这篇文章,它会很有用。

首先我想展示另一个递归的例子,它更容易一些。我在 http://www.integralist.co.uk/posts/js-recursion.html 找到它并将值从 (1, 10) 更改为 (2, 3)。
function sum(x, y) {
    if (y > 0) {
      return sum(x + 1, y - 1);
    } else {
      return x;
    }
}

sum(2, 3);

当我们启动函数时,我们检查 if 条件 y > 0。Y 是 3,所以条件为真。所以我们返回 sum(x + 1, y - 1), i。 e. sum(2 + 1, 3 - 1), i. e sum(3, 2)。

现在我们需要计算 sum(3, 2)。再次,我们从条件 y > 0 开始。Y 是 2,所以条件为真。所以我们返回 sum(x + 1, y - 1), i。 e. sum(3 + 1, 2 - 1), i. e sum(4, 1)。

现在我们需要计算 sum(4, 1)。再一次,我们检查条件 y > 0。Y 为 1,条件为真。我们返回 sum(x + 1, y - 1), i。 e.总和(4 + 1, 1 - 1), i. e sum(5, 0)。

现在我们需要计算 sum(5, 0)。我们检查条件 y > 0 并且它是假的。根据函数中的if-else,我们返回x,即5。所以sum(2, 3)返回5。

现在让我们对 sumTo() 做同样的事情;
function sumTo(n){
    if (n > 1){
        return n + sumTo(n-1)
    } else {
        return n
    }
}

sumTo(3);

从 sumTo(3) 开始。检查 n > 1 条件:3 > 1 为真,因此我们返回 n + sumTo(n - 1), i。 e. 3 + sumTo(3 - 1), i. e. 3 + sumTo(2)。

继续,我们需要计算 sumTo(2)。

为此,我们再次从检查 n > 1 条件开始函数:2 > 1 为真,因此我们返回 n + sumTo(n - 1), i。 e. 2 + sumTo(2 - 1), i. e. 2 + sumTo(1)。

继续,我们需要计算 sumTo(1)。

为此,我们再次启动函数并检查 n > 1 条件。 1 > 1 为假,因此,根据 if-else,我们返回 n, i。 e. 1. 因此, sumTo(1) 结果为 1。

现在我们将 sumTo(1) 的结果传递给上层函数 sumTo(2),在那里我们之前说过我们需要 sumTo(1) 才能继续。

SumTo(2) 返回 n + sumTo(n-1), i。 e. 2 + sumTo(2 - 1), i. e. 2 + sumTo(1), i. e. 2 + 1。因此, sumTo(2) 结果为 3。

现在我们将 sumTo(2) 的结果传递给上层函数 sumTo(3),在那里我们之前说过我们需要 sumTo(2) 才能继续。

SumTo(3) 返回 n + sumTo(n-1), i。 e. 3 + sumTo(3 - 1), i. e. 3 + sumTo(2), i. e. 3 + 3。因此,sumTo(3) 最终结果为 6。因此,sumTo(3) 返回 6。

我的错误是在任何地方我都试图插入 3 而不是 n,而 n 正在减少到 1。

感谢所有回答这个问题的人。

最佳答案

展示作品:

sumTo(4) = (4 + 3) + (2 + 1) = 10 // 4 + sumTo(3). function called four times
sumTo(3) = (3 + 2) + 1       = 6  // 3 + sumTo(2). called three times
sumTo(2) = (2 + 1)           = 3  // 2 + sumTo(1). called twice
sumTo(1) = (1)               = 1  // called once

如果你向后思考,从头开始而不是从上到下,你可能会更容易把头包起来。像这样:
sumTo(1) = 1 + sumTo(0) = 1
sumTo(2) = 2 + sumTo(1) = 3
sumTo(3) = 3 + sumTo(2) = 6
sumTo(4) = 4 + sumTo(3) = 10

请注意现在您可以如何继续添加到列表中,并且很容易计算前一个,因为您只是将两个总和相加。

事件链如下:
sumTo(3) 加 3 并调用 sumTo(2)sumTo(1) 也调用 ojit_code 并返回 3,总共为 6。

那有意义吗?如果有人有问题,我很乐意详细说明或澄清。
要理解的一个重要问题是为什么要使用递归以及何时使用递归。可以在这里找到关于这个主题的很好的讨论:When to use recursion?

递归的一个经典例子是斐波那契数列。另一个很好的例子是遍历计算机上的文件目录,例如,如果您想搜索包含其他文件夹的文件夹中的每个文件。您还可以使用递归来分解指数。


function multiplyBy10(i) {
    if ( !i ) return 0;
    return 10+multiplyBy10(i-1);
}

此函数将使用递归将数字乘以 10。掌握递归何时实用是件好事,因为有时它会让事情变得更容易。但是,最好让事情保持简单,尽可能不要让自己感到困惑。 :)

关于javascript - 需要一些帮助来理解递归,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/33751008/

10-09 02:57