我试图了解递归是如何工作的。我有了基本的想法,但细节仍不清楚。这是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。
感谢所有回答此问题的人。
答案 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。掌握递归是否切实可行是很好的,因为有时候它会使你的事情变得更容易。但是,最好保持简单,不要在任何可能的情况下混淆自己。 :)