我理解递归以及它给高效编写代码带来的好处。虽然我可以编写递归函数,但我似乎无法理解它们是如何工作的。我希望有人本能地向我解释递归。
例如,此代码:
int fact(int n)
{ if n<0:
return -1
elif n==0:
return 1
else
return n*fact(n-1)
}
这些是我的一些问题:
>
假设 n=5。进入函数后,控件转到最后一个 return 语句,因为不满足前面的条件。现在,粗略地说,计算机“写”了这样的东西:5*(fact(4))再次调用fact()函数并重复相同的过程,但现在我们有n=4。那么,编译器究竟如何将 5*4 等相乘直到 2,因为它不完全是 5*4,而是 5*fact(4)。它如何“记住”它必须乘以两个整数,以及由于我们没有提供任何明确的数据结构,它在哪里存储临时值?
再次假设n=5。同样的过程继续进行,最终n减为0。我的问题是,函数为什么/如何不返回return语句中所述的1。与我之前的问题类似,编译器如何“记住”它还存储了180个用于显示?
如果有人能给我完整的解释,让我更好更直观地理解递归,我会非常感激。
是的,对于初学者来说,递归很容易混淆。但是,你在“1”下的解释已经是正确的了。
函数将被递归调用,直到满足中断条件。在这种情况下,当n
等于0时,满足中断条件。此时,将不再进行递归调用。每个递归调用的结果都返回给调用者。呼叫者总是“等待”直到他们得到结果。这就是算法如何“知道”结果的接收者。此过程的流程由所谓的堆栈处理。
因此,在你的非正式符号中(在这个例子中n等于3):
3*(fact(2)) = 3*(2*fact(1)) = 3*(2*(1*fact(0))).
现在,n
等于 0。因此,内部事实 (0)
返回 1:
3*(2*(1*(1)))) = 3*(2*(1)) = 3*(2) = 6
你可以看到有点像这样
函数事实(int n)
就像一个类,每次调用事实(int n)
时,您都会创建该类的一个实例。通过从同一个函数创建它们(调用它们),您正在创建一个实例链。一旦达到中断条件,这些函数就开始一个接一个地返回,它们返回的值在返回语句返回n*事实(n-1)
中计算一个新值,例如返回3*事实(2);