当前位置:   article > 正文

递归与伪递归区别,Python 实现递归与尾递归_什么是伪递归

什么是伪递归

      递归函数在函数内部,可以调用其他函数。如果一个函数在内部调用自身本身,这个函数就是递归函
数。(1) 递归就是在过程或函数里调用自身。(2) 在使用递归策略时,必须有一个明确的递归结束条件,称为递归出口。

递归一般用于解决三类问题:
   (1)数据的定义是按递归定义的。(n的阶乘)
   (2)问题解法按递归实现。(回溯)
   (3)数据的结构形式是按递归定义的。(二叉树的遍历,图的搜索)
递归的缺点:
  递归解题相对常用的算法如普通循环等,运行效率较低。因此,应该尽量避免使用递归,除非没有更好的算法或者某种特定情况,递归更为适合的时候。在递归调用的过程当中系统为每一层的返回点、局部量等开辟了栈来存储,因此递归次数过多容易造成栈溢出

  1. #递归函数 act(n) = n! = 1 x 2 x 3 x ... x (n-1) x n = (n-1)! x n = fact(n-1) x n
  2. def fact(n):
  3. if n==1:
  4. return 1
  5. return n*fact(n-1)

尾递归是指,在函数返回的时候,调用自身本身,并且,return 语句不能包含表达式。这样,编译器或者解释器就可以把尾递归做优化,使递归本身无论调用多少次,都只占用一个栈帧,不会出现栈溢出的情况。

上面的fact(n)函数由于return n * fact(n ‐ 1)引入了乘法表达式,所以就不是尾递归了。要改成尾递归方式,需要多一点代码,主要是要把每一步的乘积传入到递归函数中:

  1. #定义尾递归函数
  2. def fact(n):
  3. return fact_iter(n,1)
  4. def fact_iter(num,product):
  5. if num ==1:
  6. return product
  7. return fact_iter(num-1,num*product)
  8. #测试
  9. print fact_iter(5,1)
  10. 120
  11. 可以看到,return fact_iter(num ‐ 1, num * product)仅返回递归函数本身,num ‐ 1 和num * product 在函数调用前就会被计算,不影响函数调用。
  12. fact(5)对应的fact_iter(5, 1)的调用如下:
  13.  '''
  14. #实现过程解读
  15. ===> fact_iter(5, 1)
  16. ===> fact_iter(4, 5)
  17. ===> fact_iter(3, 20)
  18. ===> fact_iter(2, 60)
  19. ===> fact_iter(1, 120)
  20. ===> 120
'''
尾递归调用时,如果做了优化,栈不会增长,因此,无论多少次调用也不会导致栈溢出。遗憾的是,大多数编程语言没有针对尾递归做优化,Python 解释器也没有做优化,所以,即使把上面的fact(n)函数改成尾递归方式,也会导致栈溢出。

更多文章请扫描下面二维码


小结
使用递归函数的优点是逻辑简单清晰,缺点是过深的调用会导致栈溢出。
针对尾递归优化的语言可以通过尾递归防止栈溢出。尾递归事实上和循环是等价的,没有循
环语句的编程语言只能通过尾递归实现循环。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/不正经/article/detail/116159
推荐阅读
相关标签
  

闽ICP备14008679号