需要一些帮助来理解递归

时间:2015-11-17 07:04:30

标签: javascript recursion

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

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

sumTo(3);

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

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

看起来像这样:

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

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

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

有人告诉我,最后一个功能会返回上一个功能,但我不知道它会用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。即总和(2 + 1,3 - 1),i。总和(3,2)。

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

现在我们需要计算总和(4,1)。再一次,我们检查条件y> 0. Y为1,条件为真。我们返回sum(x + 1,y - 1),i。即总和(4 + 1,1-1),i。总和(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。即3 + sumTo(3 - 1),i。即3 + sumTo(2)。

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

为此,我们再次检查n>启动该功能。 1条件:2> 1是真的,所以我们返回n + sumTo(n - 1),i。即2 + sumTo(2 - 1),i。即2 + sumTo(1)。

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

为此,我们再次启动该功能并检查n> 1条件。 1> 1是假的,所以,根据if-else,我们返回n,i。即因此,sumTo(1)导致1。

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

SumTo(2)返回n + sumTo(n-1),i。即2 + sumTo(2 - 1),i。即2 + sumTo(1),i。即2 + 1.因此,sumTo(2)得到3。

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

SumTo(3)返回n + sumTo(n-1),i。即3 + sumTo(3 - 1),i。即3 + sumTo(2),i。即3 + 3.因此,sumTo(3)最终得到6.因此,sumTo(3)返回6.

我的错误在于我尝试插入3而不是n,而n则减少到1。

感谢所有回答此问题的人。

3 个答案:

答案 0 :(得分:2)

没错,sumTo(n)等到sumTo(n-1)完成。
因此,sumTo(3)等待sumTo(2)
sumTo(2)等待sumTo(1)
然后sumTo(1)返回1
sumTo(2)返回2 + 1
sumTo(3)返回3 + 2 + 1

答案 1 :(得分:2)

你可以理解

sumTo(3);
returns => 3 +  sumTo(2) // n is greater than 1
                returns => 2 +  sumTo(1)
                                returns => 1 // 1 as n is not greater than 1

答案 2 :(得分: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)并返回3,总计为6。

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

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

  

考虑一个更简单的递归示例:

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

此函数将使用递归将数字乘以10。掌握递归是否切实可行是很好的,因为有时候它会使你的事情变得更容易。但是,最好保持简单,不要在任何可能的情况下混淆自己。 :)