小甲鱼零基础学习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')

这里写图片描述

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


猜你喜欢

转载自blog.csdn.net/Aka_Happy/article/details/81905803