小甲鱼零基础学习python_13 【递归实现:递归和斐波那契兔崽们的汉诺塔之谜】


递归

有人说,天才使用递归,因为递归大大的减少了程序员的代码量,而且能方便程序员实现许多的功能,但从内存等角度上,比如数据结构里提到的空间复杂度和时间复杂度来说,递归算法很多情况下的时间复杂度往往是很大的,并称不上一个好的算法,但是递归在某些方面,却又有别的方式无法媲美的优点,今天举三个例子,来温习前几天学习的递归。

1. 阶乘的两种实现:

#非递归:
def  jiecheng(n):
    y=1
    for i in range(1,n+1):     #range值取不到stop值本身,故加一
        y*=i
    return y


#递归实现:
#提前在程序开头import sys
sys.setrecursionlimit(100)   #设置最大递归层数为100 是一个python的保护措施

def jiecheng2(x):
    if x==0:       #0的阶乘为1
        y=1
    else:
        y=x*jiecheng2(x-1)
    return y

下面用求6000的阶乘对比一下两种算法的优劣:
非递归:
这里写图片描述
图片仅为结果的一小部分,但是结果仅在一眨眼的情况下就运行出来了

递归:
这里写图片描述
可以看到,这里递归6000层,超过了我开头设置的100层,所以我们把递归允许层数设置大一点,再来尝试一下:

import sys
sys.setrecursionlimit(10000)    #设置最大递归层数为10000

这里写图片描述

Process finished with exit code -1073741571 (0xC00000FD)
查看问题的根源在于递归导致的栈溢出

解决办法可参考:谁说Python不能尾递归优化


2. 斐波那契数列的两种实现:


#斐波那契数列 F(n) =  1(n=1,2) ; F(n-1)+F(n-2)


# 递归实现
def fibonacci(n):

    if(n<1):
        print('请重新输入!不可小于1!')
        y=-1
    elif(n==1):
        y=1
    elif n==2:
        y=1
    else:
        y=fibbonacci(n-1)+fibbonacci(n-2)
    return y


n=int(input('请输入几个月:\n'))
print('递归', n, ' 个月后共有:', fibonacci(n), ' 对兔子')






# 非递归实现
def fab(n):
    if(n<1):
        print('请重新输入!不可小于1!')
        y=-1
    elif(n==1):
        y=1
    elif n==2:
        y=1
    else:
        n1=1
        n2=1
        n3=1
        while(n-2>0):
            n3=n2+n1
            n1=n2
            n2=n3
            n-=1
        y=n3
    return y

print('非递归:20个月后共有:', fab(20), ' 对兔子')

这里写图片描述

对于斐波那契数列的递归和非递归算法进行测试,仍然是非递归比较优越。
但是这么说我们的递归方法,除了减少程序的代码量,就真的别无用处了吗?当然不是!
请看我们的著名的汉诺塔算法:


3. 汉诺塔的递归实现:

递归的正确使用 – 汉诺塔
第一个参数是起始柱,第二个参数是过渡柱,第三个参数是终点柱
def hanoi(n,x,y,z):
    if n==1:
        print(x, '-->', z)
    else:
        hanoi(n - 1, x, z, y) #将前n-1从x移动到y上
        print(x,'-->',z) #将最一个盘子从x移动到z上
        hanoi(n - 1, y, x, z)  #将前n-1从y移动到z上
        # 注意以上两次递归调用汉诺塔算法,起始柱,过渡柱,目标柱的变化!
n=int(input('请输入汉诺塔的层数:\n'))
hanoi(n,'x','y','z')

这里写图片描述

递归大大的减少了程序员的代码量,而且能方便程序员实现许多的功能,但是也比较吃内存吃时间,要在内存,时间和算法之间寻求一个平衡点,递归的用法还需斟酌再三,但我认为不一定是天才才可用递归,相信我们多学多练,也能找到那个平衡点的!


道01数据结构和算法绪论. mp402_谈谈算法. mp4 西03_时间复杂度和空间复杂度.mp404_时间复杂度和空间复杂度2.mp405_时间复杂度和空间复杂度3.mp4险06线性表. mp407_线性表2. mp408_线性表3. mp4品09_ 线性表4. mp410_线性表5. mp411_线性表6. mp4@12_线性表7. mp413_线性表8. mp4西14. 线性表9. mp415_线性表10. mp4 16_单链表小结:腾讯面试题. mp4品17_ 线性表12. mp418_约瑟夫问题. mp4西19_ 线性表14. mp4 20_魔术师发牌问题. mp421线性表16. mp4逾22_ 线性表17. mp423_栈和队列. mp424_栈和队列2. mp4面25_ 进制转换. mp4面26_ 栈和队列4. mp427_逆波兰计算器mp4 28_中缀表达式转换为后缀表达式01. mp4逾29_ 中缀表达式转换为后缀表达式02. mp430_栈和队列7. mp431_栈和队列8. mp4 西32递归和分治思想.mp433_递归和分治思想2. mp434_汉诺塔. mp4 35_八皇后问题. mp4 四36_字符串.mp4 二37_ KMP算法. mp4 四71斐波那契查找(黄金分割法查找).38_ KMP算法2. mp4 立39_ KMP算法之NEXT数组代码原理分析. mp4二40_ KMP算法之实现及优化. mp4二41树. mp4 四42_树的存储结构. mp443_树的存储结构2. mp4四44_二艾树. mp445_二叉树2. mp4 46_二又树的存数结构. mp447_二又树的遍历. mp4 48_二丈树的建立和遍历算法. mp4四49_线索二叉树. mp4 50_线索二又树代码实现. mp4 画51_树、森林及二又树的相互转换. mp452_赫夫曼树. mp453_赫夫曼编码. mp4 四54_赫夫曼编码C语言实现. mp4口55_图. mp4 逾56_图的定义与术语2. mp457_图的存储结构. mp4 58_图的存储结构(邻接表) . mp4 59_图的存储结构(十字链表、邻接多重表、边集数组) . mp4四93堆排序的代码实现mp460_图的遍历(深度优先遍历) . mp4 品94归并排序. mp4 四61_马踏棋盘算法(骑士周游问题) . mp4 95归并排序(迭代实现) . mp4品62_图的遍历(广度优先遍历) . mp4 國96快速排序.mp4 63_最小生成树(普里姆算法) . mp4 二97快速排序的优化mp464_最小生成树( 克鲁斯卡尔算法) . mp4 立98总结回顾.mp4画65_最短路径(迪杰斯特拉算法).mp466_最短路径( 弗洛伊德算法) . mp4口67拓扑排序. mp4二68关键路径.mp4口69_查找算法. mp4 画69关键路径(代码讲解).mp4
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值