参考课程:清华大学博士讲解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)=。算法的时间复杂度很高,n值过大会导致计算机内存爆炸[○・`Д´・ ○]
移动64个圆盘需要经过18446744073709551616步,距离世界毁灭还剩584942417355.072年~~(*^▽^*)