递归是函数调用自身的过程,满足递归的两个条件:1、调用自身;2、结束条件。
# 下面这个函数不是递归,因为它只调用了自己,但是没有结束条件,所以他会一直执行下去
def fun1(x):
print(x)
fun1(x-1)
# 以下两个函数都是使用了递归,既有调用自身,也有结束条件
def fun2(x):
if x>1:
print(x)
fun2(x-1)
def fun3(x):
if x>1:
fun3(x-1)
print(x)
两个递归还有不同之处,就是他们的打印顺序不一样
下面画图进行说明:代码沿着红线从上往下进行,黑框表示程序输出,蓝色框表示调用自身
fun2是先打印再调用自己,假如函数输入的是5,那么得到的就是:5,4,3,2
fun3是先调用自己再打印,假如函数输入为5,那么得到的就是:2,3,4,5
最为经典的递归应用为汉诺塔游戏,
汉诺塔游戏规则为:
1、有三根相邻的柱子,标号为A,B,C。
2、A柱子上从下到上按金字塔状叠放着n个不同大小的圆盘。
3、现在把所有盘子一个一个移动到柱子B上,并且每次移动同一根柱子上都不能出现大盘子在小盘子上方。
如果盘子只用3个的话,我们可以很快得到正确的方法,但是如果盘子有20个,40个甚至更多,我们要移动的次数就会变得更多,为了轻松得到正确方法,我们可以通过递归的方式来解决这个问题。
思路:实现盘子的搬移总共需要3步,假设有n个盘子,从左到右分别为A柱子,B柱子,C柱子
1、将n-1个盘子全部从A柱子通过C柱子的辅助移动到B柱子
2、将第n个盘子移动到C柱子
3、将n-1个盘子从B柱子通过A柱子的辅助移动到C柱子
网上的解释都比较复杂,这里我通过自己的语言来解释一下,
因为盘子的摆放方式都是小的放在大的上面,所以最大的在底部,想要将最大的移动到C柱子,那么这个时候除了最大的盘子,其他的都应该在B柱子,盘子移动的过程我们不管,我们只需要知道结果,这个时候就完成了第一、二步,我们就不再考虑最大的盘子了,
接下来就需要移动倒数第二个盘子了,倒数第二个盘子现在在B柱子的最下面,那么想要让倒数第二个盘子从B柱子移动到C柱子,那么除了倒数第二个盘子,其他的盘子应该都在A柱子,过程依旧不管,这个时候我们就完成了第三步了,
发现了没有这个时候我们已经完成了两个盘子的移动,而其他所有的盘子都在最开始的位置,我们只需要重复这个过程,所有的盘子就将会自然而然的到达C柱子。
聪明的你这个时候应该知道这个递归是使用了fun2还是fun3的方法了吧,没错就是fun3的方法,代码如下:
def hanoi(n,a,b,c):
while n>0:
hanoi(n-1,a,c,b)
print("%s-->%s" % (a,c))
hanoi(n-1,b,a,c)