详解python使用递归、尾递归、循环三种方式实现斐波那契数列


Posted in Python onJanuary 16, 2018

在最开始的时候所有的斐波那契代码都是使用递归的方式来写的,递归有很多的缺点,执行效率低下,浪费资源,还有可能会造成栈溢出,而递归的程序的优点也是很明显的,就是结构层次很清晰,易于理解

可以使用循环的方式来取代递归,当然也可以使用尾递归的方式来实现。

尾递归就是从最后开始计算, 每递归一次就算出相应的结果, 也就是说, 函数调用出现在调用者函数的尾部, 因为是尾部, 所以根本没有必要去保存任何局部变量. 直接让被调用的函数返回时越过调用者, 返回到调用者的调用者去。尾递归就是把当前的运算结果(或路径)放在参数里传给下层函数,深层函数所面对的不是越来越简单的问题,而是越来越复杂的问题,因为参数里带有前面若干步的运算路径。尾递归是极其重要的,不用尾递归,函数的堆栈耗用难以估量,需要保存很多中间函数的堆栈。直接递归的程序中需要保存之前n步操作的所有状态极其耗费资源,而尾递归不需要,尾部递归是一种编程技巧。如果在递归函数中,递归调用返回的结果总被直接返回,则称为尾部递归。尾部递归的函数有助将算法转化成函数编程语言,而且从编译器角度来说,亦容易优化成为普通循环。这是因为从电脑的基本面来说,所有的循环都是利用重复移跳到代码的开头来实现的。如果有尾部归递,就只需要叠套一个堆栈,因为电脑只需要将函数的参数改变再重新调用一次

为了加深对尾递归、递归和循环的对比,这里以斐波那契数列的实现举例:

#!usr/bin/env python  
#encoding:utf-8    
''''''' 
__Author__:沂水寒城 
功能:尾递归 
'''   
import time 
def Fib_recursion(num): 
  ''''' 
  直接使用递归法求解斐波那契数量的第num个数字 
  ''' 
  if num<2: 
   return num  
  return Fib_recursion(num-1)+Fib_recursion(num-2) 
 
def Fib_tail_recursion(num,res,temp): 
  ''''' 
  使用尾递归法求解斐波那契数量的第num个数字 
  ''' 
  if num==0: 
    return res  
  else: 
    return Fib_tail_recursion(num-1, temp, res+temp)  
def Fib_circle(num): 
  ''''' 
  直接使用循环来求解 
  ''' 
  a=0 
  b=1 
  for i in range(1,num): 
    c=a+b 
    a=b 
    b=c  
  return c  
  
if __name__ == '__main__': 
  num_list=[5,10,20,30,40,50] 
  for num in num_list: 
    start_time=time.time() 
    print Fib_recursion(num) 
    end_time=time.time() 
    print Fib_tail_recursion(num,0,1) 
    end_time2=time.time() 
    print Fib_circle(num) 
    end_time3=time.time() 
    print '正在求解的斐波那契数字下标为%s' %num 
    print '直接递归耗时为 :', end_time-start_time 
    print '尾递归调用耗时为:', end_time2-end_time 
    print '直接使用循环耗时为:', end_time3-end_time2

结果如下:

5 
5 
5 
正在求解的斐波那契数字下标为5 
直接递归耗时为 : 6.38961791992e-05 
尾递归调用耗时为: 2.31266021729e-05 
直接使用循环耗时为: 1.97887420654e-05 
55 
55 
55 
正在求解的斐波那契数字下标为10 
直接递归耗时为 : 6.60419464111e-05 
尾递归调用耗时为: 3.31401824951e-05 
直接使用循环耗时为: 1.8835067749e-05 
6765 
6765 
6765 
正在求解的斐波那契数字下标为20 
直接递归耗时为 : 0.00564002990723 
尾递归调用耗时为: 3.09944152832e-05 
直接使用循环耗时为: 2.09808349609e-05 
832040 
832040 
832040 
正在求解的斐波那契数字下标为30 
直接递归耗时为 : 0.39971113205 
尾递归调用耗时为: 1.69277191162e-05 
直接使用循环耗时为: 1.19209289551e-05 
102334155 
102334155 
102334155 
正在求解的斐波那契数字下标为40 
直接递归耗时为 : 39.0365440845 
尾递归调用耗时为: 2.19345092773e-05 
直接使用循环耗时为: 1.78813934326e-05 
12586269025 
12586269025 
12586269025 
正在求解的斐波那契数字下标为50 
直接递归耗时为 : 4915.68643498 
尾递归调用耗时为: 2.19345092773e-05 
直接使用循环耗时为: 2.09808349609e-05

画图图表更加清晰地可以看到差距:

详解python使用递归、尾递归、循环三种方式实现斐波那契数列

因为差距太大,导致尾递归和循环的两种方式的时间增长几乎是水平线,而直接递归的时间增长接近90度。

这一次,感觉自己好有耐心,一直就在那里等着程序出结果,可以看到三者的时间对比状况,很明显的:直接递归的时间增长的极快,而循环的性能还要优于尾递归,这就告诉我们尽量减少递归的使用,使用循环的方式代替递归无疑是一种提高程序运行效率的方式。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Python 相关文章推荐
python抓取网页图片并放到指定文件夹
Apr 24 Python
Python程序设计入门(2)变量类型简介
Jun 16 Python
用不到50行的Python代码构建最小的区块链
Nov 16 Python
Python实现查找最小的k个数示例【两种解法】
Jan 08 Python
Python设置matplotlib.plot的坐标轴刻度间隔以及刻度范围
Jun 25 Python
python文件读写代码实例
Oct 21 Python
python数字类型math库原理解析
Mar 02 Python
python实现读取类别频数数据画水平条形图案例
Apr 24 Python
python:解析requests返回的response(json格式)说明
Apr 30 Python
自定义Django_rest_framework_jwt登陆错误返回的解决
Oct 18 Python
pytorch中的model.eval()和BN层的使用
May 22 Python
Django+Celery实现定时任务的示例
Jun 23 Python
Python+tkinter模拟“记住我”自动登录实例代码
Jan 16 #Python
Python利用字典将两个通讯录文本合并为一个文本实例
Jan 16 #Python
Python爬虫爬取一个网页上的图片地址实例代码
Jan 16 #Python
Python+Turtle动态绘制一棵树实例分享
Jan 16 #Python
Python实现七彩蟒蛇绘制实例代码
Jan 16 #Python
答题辅助python代码实现
Jan 16 #Python
python实现百万答题自动百度搜索答案
Jan 16 #Python
You might like
PHP Zip解压 文件在线解压缩的函数代码
2010/05/26 PHP
php将字符串全部转换成大写或者小写的方法
2015/03/17 PHP
PHP简单实现生成txt文件到指定目录的方法
2016/04/25 PHP
OfflineSave离线保存代码再次发布使用说明
2007/05/23 Javascript
情人节专属 纯js脚本1k大小的3D玫瑰效果
2012/02/11 Javascript
jquery插件制作 图片走廊 gallery
2012/08/17 Javascript
js 如何实现对数据库的增删改查
2012/11/23 Javascript
SyntaxHighlighter 3.0.83使用笔记
2015/01/26 Javascript
JavaScript插件化开发教程 (四)
2015/01/27 Javascript
JS实现让访问者自助选择网页文字颜色的方法
2015/02/24 Javascript
Lab.js初次使用笔记
2015/02/28 Javascript
jquery中$each()方法的使用指南
2015/04/30 Javascript
详解AngularJS中的作用域
2015/06/17 Javascript
输入法的回车与消息发送快捷键回车的冲突解决方法
2016/08/09 Javascript
开源免费天气预报接口API及全国所有地区代码(国家气象局提供)
2016/12/26 Javascript
angular实现商品筛选功能
2017/02/01 Javascript
js实现数字递增特效【仿支付宝我的财富】
2017/05/05 Javascript
Vue学习笔记进阶篇之单元素过度
2017/07/19 Javascript
jQuery UI 实例讲解 - 日期选择器(Datepicker)
2017/09/18 jQuery
webpack 样式加载的实现原理
2018/06/12 Javascript
小程序实现留言板
2018/11/02 Javascript
JavaScript数据结构与算法之二叉树添加/删除节点操作示例
2019/03/01 Javascript
python 默认参数问题的陷阱
2016/02/29 Python
使用NumPy和pandas对CSV文件进行写操作的实例
2018/06/14 Python
python2爬取百度贴吧指定关键字和图片代码实例
2019/08/14 Python
Python笔记之代理模式
2019/11/20 Python
python列表返回重复数据的下标
2020/02/10 Python
Python内存映射文件读写方式
2020/04/24 Python
基于Python组装jmx并调用JMeter实现压力测试
2020/11/03 Python
Python urllib3软件包的使用说明
2020/11/18 Python
Omio意大利:全欧洲低价大巴、火车和航班搜索和比价
2017/12/02 全球购物
Kiehl’s科颜氏西班牙官方网站:源自美国的植物护肤品牌
2020/02/22 全球购物
院领导写的就业推荐信
2014/03/09 职场文书
干部作风整顿自我剖析材料和整改措施
2014/09/18 职场文书
淮海战役观后感
2015/06/11 职场文书
Python查找算法的实现 (线性、二分,分块、插值查找算法)
2022/04/24 Python