递归
❖递归是一种解决问题的方法,其精髓在于
将问题分解为规模更小的相同问题,
持续分解,直到问题规模小到可以用非常简单直
接的方式来解决。
递归的问题分解方式非常独特,其算法方面的明
显特征就是:在算法流程中调用自身。
❖给定一个列表,返回所有数的和
def listsum(numList):
if len(numList)==1:
return numList[0]
else:
return numList[0]+listsum(numList[1:]) #调用自身
print(listsum([1, 1, 4, 5, 1, 4]))
1,问题分解为更小规模的相同问题,并表现为
“调用自身”
2对“最小规模”问题的解决:简单直接
递归三定律
1,递归算法必须有一个基本结束条件(最小规
模问题的直接解决)
2,递归算法必须能改变状态向基本结束条件演
进(减小问题规模)
3,递归算法必须调用自身(解决减小了规模的
相同问题
递归调用的实现
❖当一个函数被调用的时候,系统会把调用
时的现场数据压入到系统调用栈
每次调用,压入栈的现场数据称为栈帧
当函数返回时,要从调用栈的栈顶取得返回地址
,恢复现场,弹出栈帧,按地址返回
❖在调试递归算法程序的时候经常会碰到这
样的错误:RecursionError
递归的层数太多,系统调用栈容
复杂递归问题:汉诺塔
一次只能搬1个盘子
大盘子不能叠在小盘子上
如果有64个盘子需要的移动次数为264-1 = 18,446,744,073,709,551,615次
从递归三定律来分析汉诺塔问题
基本结束条件(最小规模问题),如何减小规模,调用自身
假设有五个盘子,在一号柱子上,需要挪到三号柱子上
如果能有办法把最上面的一摞4个盘子统统挪到2柱,那问题就好解决了:
把剩下的最大号盘子直接从1柱挪到3柱,再用同样的办法把2柱上的那一摞4个盘子挪到3柱,就完成了整个移动
接下来问题就是解决4个盘子如何能从1挪到2?
此时问题规模已经减小!
同样是想办法把上面的一摞3个盘子挪到3柱,把剩下最大号盘子从1挪到2柱,再用同样的办法把一摞3个盘子从3挪到2柱
一摞3个盘子的挪动也照此:
分为上面一摞2个,和下面最大号盘子
那么2个盘子怎么移动?
不行,就再分解为1个盘子的移动
将盘片塔从开始柱,经由中间柱,移动到目标柱:
首先将上层N-1个盘片的盘片塔,从开始柱,经由目标柱,移动到中间柱;然后将第N个(最大的)盘片,从开始柱,移动到目标柱;最后将放置在中间柱的N-1个盘片的盘片塔,经由开始柱,移动到目标柱。
基本结束条件,也就是最小规模问题是:
1个盘片的移动问题