赞
踩
递归函数在函数内部,可以调用其他函数。如果一个函数在内部调用自身本身,这个函数就是递归函
数。(1) 递归就是在过程或函数里调用自身。(2) 在使用递归策略时,必须有一个明确的递归结束条件,称为递归出口。
- #递归函数 act(n) = n! = 1 x 2 x 3 x ... x (n-1) x n = (n-1)! x n = fact(n-1) x n
- def fact(n):
- if n==1:
- return 1
- return n*fact(n-1)
尾递归是指,在函数返回的时候,调用自身本身,并且,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)
- #测试
- print fact_iter(5,1)
- 120
- 可以看到,return fact_iter(num ‐ 1, num * product)仅返回递归函数本身,num ‐ 1 和num * product 在函数调用前就会被计算,不影响函数调用。
- fact(5)对应的fact_iter(5, 1)的调用如下:
- '''
- #实现过程解读
- ===> fact_iter(5, 1)
- ===> fact_iter(4, 5)
- ===> fact_iter(3, 20)
- ===> fact_iter(2, 60)
- ===> fact_iter(1, 120)
- ===> 120
'''
尾递归调用时,如果做了优化,栈不会增长,因此,无论多少次调用也不会导致栈溢出。遗憾的是,大多数编程语言没有针对尾递归做优化,Python 解释器也没有做优化,所以,即使把上面的fact(n)函数改成尾递归方式,也会导致栈溢出。
更多文章请扫描下面二维码
小结
使用递归函数的优点是逻辑简单清晰,缺点是过深的调用会导致栈溢出。
针对尾递归优化的语言可以通过尾递归防止栈溢出。尾递归事实上和循环是等价的,没有循
环语句的编程语言只能通过尾递归实现循环。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。