02递归算法及汉诺塔问题

本文介绍了递归的概念,强调了合法递归必须包含结束条件,并通过示例解释了非法递归可能导致的RecursionError。同时,详细阐述了汉诺塔问题的递归解决方案,通过分解步骤展示了如何利用递归解决复杂问题。最后,提供了Python代码实现汉诺塔问题的递归算法,探讨了其时间复杂度和应用场景。
摘要由CSDN通过智能技术生成

参考课程:清华大学博士讲解Python数据结构与算法(完整版)全套100节_哔哩哔哩_bilibili

递归就是函数运行过程中不断调用自身,即:我调用我自己。

合法的递归必须要有结束条件。

以下程序:

def func1(x):
    print(x)
    func1(x-1)

不是合法的递归,因为没有结束条件,程序会无休无止地运行下去。

同理,

def func2(x):
    if x>0:
        print(x)
        func2(x+1)

也不是合法的递归,看似有了“x>0”的约束条件,实际上x不停变大,这个条件并不能使程序停止运行。运行结果是这样:

RecursionError: maximum recursion depth exceeded while calling a Python object

因为python默认递归深度为1000,即调用自己1000次,超过这个深度就会被截停。否则,这样没有截止条件的程序将导致系统内存崩溃。

而以下程序:

def func3(x):
    if x>0:
        print(x)
        func3(x-1)
def func4(x):
    if x>0:
        func4(x-1)
        print(x)

都是合法的递归,因为无论x取多少,不停-1都会有<0的时候,程序截止。

func3和func4的区别在于,func3先打印,后调用;而func4先调用,后打印。运行完毕后,对于同一个位置的x,func3对应位置的数字比func4大1.

递归算法的应用:汉诺塔问题

 假设圆盘从小到大依次编号1,2,3……,柱子从左到右依次编号A,B,C。

一次性计算64个圆盘的移动步骤很难,但是计算两个圆盘的移动步骤很简单。

第一步:1从A移动到B

第二步:2从A移动到C

第三步:1从B移动到C

而在n个圆盘的移动步骤中,可以根据数学归纳法,仿照两个圆盘的移动步骤,即:

第一步:将n-1个盘子移动到B(中间经过C)

第二步:把第n个盘子从A移动到C

第三步:把n-1个盘子从B移动到C(中间经过A)

这样,该问题就变成了一个比原问题规模小了1的子问题,按照这种方法不断拆解,就可以将该问题逐渐拆解掉。

运行代码如下:

def hanoi(n,a,b,c):
    if n>0:
        hanoi(n-1,a,c,b)#对应步骤一,需要h(n-1)个小步骤
        print("把%s号圆盘从柱子%s移动到柱子%s"%(n,a,c))#对应步骤二,需要1个小步骤。本次递归解决第n个圆盘的放置,之后是第n-1个,第n-2个……
        hanoi(n-1,b,a,c)#对应步骤三,需要h(n-1)个小步骤
hanoi(4,"A柱","B柱","C柱")   

(代码来源:哔哩哔哩用户@基金定投小学生)

由此可知,h(n)=h(n-1)+1+h(n-1),h(n)=2^{n}。算法的时间复杂度很高,n值过大会导致计算机内存爆炸[○・`Д´・ ○]

移动64个圆盘需要经过18446744073709551616步,距离世界毁灭还剩584942417355.072年~~(*^▽^*)

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值