我了解递归及其对有效编写代码的好处。虽然我可以编写递归函数的代码,但似乎无法将其工作原理全神贯注。我希望有人能本能地解释我的递归。
例如,此代码:
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直到2,因为它不是完全5 * 4而是5 * fact(4)。
再次假设n = 5。相同的过程继续进行,最终n递减为0。我的问题是,为什么/为什么函数不像return语句中那样简单地返回1。与我之前的问题类似,编译器如何“记住”它还存储了180个供显示?
如果有人向我完全解释这一点,以便能够更好,更直观地理解递归,我将非常感谢。
答案 0 :(得分:2)
是的,对于初学者而言,递归可能会造成混乱。但是,您已经在正确的轨道上,在“ 1”下进行了解释。
该函数将递归调用,直到满足中断条件为止。在这种情况下,当n
等于0时满足中断条件。此时,将不再进行递归调用。每次递归调用的结果都将返回给调用者。呼叫者总是“等待”直到获得结果。这就是算法“知道”结果接收者的方式。此过程的流程由所谓的堆栈处理。
因此,以您的非正式记号(在此示例中,n等于3):
3*(fact(2)) = 3*(2*fact(1)) = 3*(2*(1*fact(0))).
现在,n
等于0。内部fact(0)
返回1:
3*(2*(1*(1)))) = 3*(2*(1)) = 3*(2) = 6
答案 1 :(得分:0)
您会看到类似这样的
函数fact(int n)
就像一个类,每次调用fact(int n)
时都会创建该类的实例。通过从同一函数创建它们(调用它们),就可以创建实例链。达到中断条件后,这些函数将开始一个接一个地返回,并且它们返回的值将在return语句return n*fact(n-1)
中计算出一个新值,例如return 3*fact(2);