6.6 递归函数
在函数内部,可以调用其他函数。如果一个函数在内部直接或者间接调用函数自身,这个函数就是递归函数。
例如,我们用fact(n)函数来计算n的阶乘,即
fact(n) = n! = n x (n - 1) x (n - 2) ... x 3 x 2 x 1
根据阶乘的特点,可以得出这个结果:
fact(n) = n x fact(n - 1)
依此类推:
fact(n - 1) = (n - 1) x fact(n - 1 - 1)
直到:
fact(2) = 2 x fact(2 - 1)
这里fact(1)的值确定之后,就可以逐级算出每一个fact(n - 1),直到最后的fact(n),这就是递归函数的思维。
上面的函数可以写成:6.14-递归阶乘.py
# 使用递归函数求阶乘
def fact(n):
if n == 1:
res = 1
else:
res = n * fact(n - 1)
return res
print(fact(5))
执行结果为:
120
计算fact(5)时,可以根据函数定义得到计算过程如下:
===> fact(5)
===> 5 * fact(4)
===> 5 * (4 * fact(3))
===> 5 * (4 * (3 * fact(2)))
===> 5 * (4 * (3 * (2 * fact(1))))
===> 5 * (4 * (3 * (2 * 1)))
===> 5 * (4 * (3 * 2))
===> 5 * (4 * 6)
===> 5 * 24
===> 120
在还没有求出fact(1)的时候,前面的fact(5), fact(4)等函数的调用都没有返回,等在那里,等待fact(n - 1)的结果回来,好计算本次函数的返回值n*fact(n - 1),直到fact(1)返回了确定的值1,然后逐级的fact(2)有了结果,然后fact(3)也有了结果,最后fact(5)也返回了确定的结果值,于是递归函数计算出了结果。可以使用断点调试的方法查看函数递归调用的情况。
于是在逐级的等待中,fact(5), fact(4)等函数没有返回,没有返回时的函数,是放在一个栈的数据结构中的,调用结束时,从栈中删除。由于递归函数在执行过程中,前面n - 1个函数都没有返回,所以都在栈中堆积。栈的大小有限,如果超出了范围,就会导致栈溢出。所以递归函数的调用次数不能过多。