繁体   English   中英

需要一些帮助才能理解递归

[英]Need some help to understand 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到上面的函数,但我不知道它会用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),即sum(2 + 1,3-1),i。 总和(3,2)。

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

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

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

为此,我们再次从检查n> 1条件启动函数:2> 1为真,所以我们返回n + sumTo(n - 1),即2 + sumTo(2 - 1),即2 + sumTo( 1)。

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

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

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

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

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

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

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

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

没错, 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

你可以理解

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

展示作品:

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。

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

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

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

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM