提问者:小点点

有人能直观地解释一下这段代码吗?


我理解递归以及它给高效编写代码带来的好处。虽然我可以编写递归函数,但我似乎无法理解它们是如何工作的。我希望有人本能地向我解释递归。

例如,此代码:

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个用于显示?

    如果有人能给我完整的解释,让我更好更直观地理解递归,我会非常感激。


  • 共2个答案

    匿名用户

    是的,对于初学者来说,递归很容易混淆。但是,你在“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);