递归与伪递归区别,Python 实现递归与尾递归
来源:互联网 发布:全国淘宝店有多少家 编辑:程序博客网 时间:2024/05/17 08:31
递归函数在函数内部,可以调用其他函数。如果一个函数在内部调用自身本身,这个函数就是递归函
数。(1) 递归就是在过程或函数里调用自身。(2) 在使用递归策略时,必须有一个明确的递归结束条件,称为递归出口。
递归一般用于解决三类问题:
(1)数据的定义是按递归定义的。(n的阶乘)
(2)问题解法按递归实现。(回溯)
(3)数据的结构形式是按递归定义的。(二叉树的遍历,图的搜索)
递归的缺点:
递归解题相对常用的算法如普通循环等,运行效率较低。因此,应该尽量避免使用递归,除非没有更好的算法或者某种特定情况,递归更为适合的时候。在递归调用的过程当中系统为每一层的返回点、局部量等开辟了栈来存储,因此递归次数过多容易造成栈溢出。
#递归函数 act(n) = n! = 1 x 2 x 3 x ... x (n-1) x n = (n-1)! x n = fact(n-1) x ndef 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)函数改成尾递归方式,也会导致栈溢出。
更多文章请扫描下面二维码
小结
使用递归函数的优点是逻辑简单清晰,缺点是过深的调用会导致栈溢出。
针对尾递归优化的语言可以通过尾递归防止栈溢出。尾递归事实上和循环是等价的,没有循
环语句的编程语言只能通过尾递归实现循环。
0 0
- 递归与伪递归区别,Python 实现递归与尾递归
- 递归与尾递归
- 递归与尾递归
- 递归与尾递归
- 递归与尾递归
- 递归与尾递归
- 递归与尾递归
- 递归与尾递归
- 递归与尾递归
- 递归与尾递归
- 递归与尾递归
- 递归与尾递归
- 递归与尾递归
- 递归与尾递归
- 递归与尾递归
- 递归与尾递归
- 递归与尾递归
- 递归与尾递归
- 正在逐渐流行的分屏式设计,常见的玩法有哪些?
- 页面元素绑定函数返回的值
- 收藏
- poj 1062 昂贵的聘礼 【最短路径-Dijkstra】
- eclipse中如何向开源中国(码云)上传代码
- 递归与伪递归区别,Python 实现递归与尾递归
- 那些年,我们一起写过的“单例模式”
- Shell脚本编程30分钟入门
- Fiddler教程:fiddler抓包时,出现的 tunnel to
- WebCollector爬虫学习记录(一)爬取国际石油网知识板块
- 简析数据库范式
- Ubuntu16.04 搭建VPN服务
- noi-7599-石头剪子布
- 《机导》学习感悟(一)