2019.7.21 递归函数

递归函数:函数运行过程中会调用自身的函数

举例:阶乘 n!=1×2×3×……×(n-1)×n

def fact(n):
    if n==1:
        return 1
    return n*fact(n-1)
print(fact(1))
print(fact(5))
print(fact(10))

#结果
1
120
3628800

 

递归函数的构建有两个条件:1、有递归终止条件(如上文的if n==1)  2、能够达到递归终止条件(上文fact(n-1),n在每一层的递归中是不断减小的,而且可以减小到1)

 

递归的实现在计算机中依靠栈,递归层数越多则栈越多,所以要预防递归次数过多引起的栈溢出

fact(1000)
Traceback (most recent call last):
  File "<input>", line 1, in <module>
  File "C:/Users/Le/Desktop/Test/T2.py", line 4, in fact
    return n*fact(n-1)
  File "C:/Users/Le/Desktop/Test/T2.py", line 4, in fact
    return n*fact(n-1)
  File "C:/Users/Le/Desktop/Test/T2.py", line 4, in fact
    return n*fact(n-1)
  [Previous line repeated 986 more times]
  File "C:/Users/Le/Desktop/Test/T2.py", line 2, in fact
    if n==1:
RecursionError: maximum recursion depth exceeded in comparison

 

可以通过尾递归的方式解决栈溢出问题,尾递归是指,在函数返回时调用自身,且return语句不能包含表达式。这样,编译器或者解释器就可以把尾递归优化,使得递归函数无论调用多少次本身,都只占用一个栈。

 

尾递归在本质上与循环等价,可以将循环视为特殊的尾递归

 

上文的fact(n),由于return n*fact(n-1)引入了乘法,所以不是尾递归,要修改成尾递归的方式,就要把每一步的乘积传入到递归函数中:

def fact(n):
    return fact_iter(n,1)
def fact_iter(num,product):
    if num==1:
        return product
    return fact_iter(num-1,num*product)

fact_iter函数的return仅返回递归函数本身,不包含其他表达式,作为参数传入的乘法会在函数调用前计算好,不影响函数的调用,这样就构成了一个尾递归。

 

尾递归调用时,如果做了优化,栈不会增长,无论调用多少次递归函数都不会栈溢出

遗憾的是,大多数编程语言包括Python都没有对尾递归做优化,因此即使用了尾递归,也会在递归层次很大时导致栈溢出

 

What???这跟“欲练此功 必先自宫 即使自宫 未必成功”有什么区别??

 

https://www.liaoxuefeng.com/wiki/897692888725344/897693398334720

 

posted @ 2019-07-21 10:25  ShineLe  阅读(312)  评论(0)    收藏  举报