目录
关于递归
当问题可以用一个逻辑反复解决时,即一个问题转化为一个新的问题,而这个新的问题的解决方法仍与原问题的解法相同,就可以使用递归算法解决。
递归的经典例子是阶乘
def f(n):
if n == 0:
return 1
else:
return n*f(n-1)
递归不是循环,当递归到底了,就需要一个能直接计算出值的表达式。阶乘揭示了递归的两个关键特征,也是递归算法的核心。
- 存在一个或多个基例,基例不需要递归,它是确定的表达式 (比如0的阶乘为1就是递归的基例)
- 递归链要以一个或多个基例结尾
核心思想
以阶乘算法为例,我们主要考虑两个核心问题:
- 确定基例对应的算法
- 不满足基例时对应的算法
实例
1.字符串反转
将字符串看为两部分:首字符和剩余字符,只需将首字符放到剩余字符后面就可以实现反转。
递归实现思路
对于没有剩余字符(一个字符)的,那么它的剩余字符s[1:0]的值是空字符串 ''(切片对于超出索引的返回值为对应的空值,而索引则报错) ,也就是False。这样我们就确定了基例的条件,对于一个字符,返回它本身就好了
如果是两个字符呢?只需将首字符放到剩余字符后面就可以实现反转,对于剩余字符仍是相同逻辑所以再次对剩余字符进行相同操作即 reverse(s[1:])
def reverse(s):
if s == '':
return s
else:
return reverse(s[1:]) + s[0]
2.绘制科赫(koch)曲线
一个边长为1的等边三角形,取每边中间的三分之一,接上去一个形状完全相似的但边长为其三分之一的三角形,结果是一个六角形。取六角形的每个边做同样的变换,即在中间三分之一接上更小的三角形,以此重复,直至无穷。外界的变得原来越细微曲折,形状接近理想化的雪花。这条曲线叫科克曲线。
递归实现思路
同样的思路,对于0阶曲线,只是条直线,基列条件为 n == 0时 执行 t.fd(length)
对于1阶科赫曲线,每一段直线上分成三段,每一段由边长为length/3的等边三角形取代,具体绘制方法如下。
同样的逻辑对于高阶科赫曲线,可使用递归解决。
import turtle as t
def kohc(length, n):
if n == 0:
t.fd(length)
else:
for angle in [0, 60, -120, 60]:
t.left(angle)
kohc(length / 3, n - 1)
效果如下
3.汉诺塔问题
汉诺塔(Tower of Hanoi),又称河内塔。源自印度古老传说的一个游戏,大梵天创造世界的时候做了三根金刚石柱子,在一根柱子上从下往上按照大小顺序摞着64片黄金圆盘。大梵天命令婆罗门把圆盘从下面开始按大小顺序重新摆放在另一根柱子上。并且规定,在小圆盘上不能放大圆盘,在三根柱子之间一次只能移动一个圆盘。
递归实现思路
如果只有一个盘子,我们只需移动到c柱上即可,那么基例条件是 当盘子数n == 1
- 思考Cz柱盘子为2时该如何移动
- 思考为什么这里print内不能写成 'A -> C'
具体实现方法如下:
def hanoi (n,a,b,c):
if n == 1 :
print(f'{a} -> {c}')
else:
hanoi(n-1,a,c,b)
print(f'{a} -> {c}')
hanoi(n-1,b,a,c)
hanoi(3,'A','B','C')
需要注意的是,递归函数的所有输出操作必须在基例中进行或者与基例一致!不要尝试理解多层递归是如何运行的,递归是抽象的,具象化非常复杂而且弊大于利!
END