在廖大神学习网站上学到递归的时候,有这样一个练习:
题目:请编写move(n, a, b, c)函数,它接收参数n,表示3个柱子A、B、C中第1个柱子A的盘子数量,然后打印出把所有盘子从A借助B移动到C的方法,
期待输出:
A –> C
A –> B
C –> B
A –> C
B –> A
B –> C
A –> C
这篇文章对这个学习做一个总结。
代码敬上
简洁版:
def move(n, a, b, c):
if n==1:
print(a,'-->',c)
return
move(n-1,a,c,b)
move(1,a,b,c)
move(n-1,b,a,c) c
move(3, 'A', 'B', 'C')
按思路注释版:
def move(n, a, b, c):
if n==1: #n值为1 而非定义n=1
return print(a,'-->',c)#只有一个盘的时候,a移动到c;
move(n-1,a,c,b) #(第一步)进入递归,直到n-1==1时,实现a->b 传入递归的参数的n值改变,递归结束后n值恢复,注意传入函数的参数的位置;
move(1,a,b,c) #(第二步)接着执行,调用自身函数实现a->c,可替换为print(a,'->',c),因为只是将A柱底最大盘移至C柱的过程(第二步);
move(n-1,b,a,c) #(第三步)将位于b处的n-1个盘从b经由a移至c ,上一个递归后n恢复为调用函数传入的n,进入递归,实现b->c;
move(3, 'A', 'B', 'C')
首先,汉诺塔移动的原理:
汉诺塔是将所有盘子(n个)从A柱挪至C柱,大盘必须在小盘下方。注意却分思路和具体步骤。
思路
为将n-1个盘子(除了最底下一枚)从A移到B(第一步); 然后将位于A的最后一枚最大盘移至C(第二步); 再将B柱上所有盘移至C柱(第三步)。
具体步骤便是需要实现上面第一步,要实现第一步又要先移动(n-1)上面的(n-1)-1个盘子,所以这是典型的递归原理。
注:刚开始我混淆了思路与具体步骤,想到了具体步骤但看思路的时候发现与每次只能移动一个要求不同,原因是步骤是上往下移动从开始到结果,而递归是从结果到开始得到最小值,再从开始到结果。
最小的子问题就是:将一块盘子从A移动到C柱,“大于1”的子问题是:将两块盘子从A移动到C柱,不妨在草稿纸上画个图,显然有三个步骤:
1.将最上面的盘子从A移动到B
2.将A下面的盘子从A移动到C
3.将B上的盘子移动到C
而程序调用自身则是逐次对(n-1)个盘子进行同样的操作就可以解决n个盘子移动的问题。
只需以上三步分析就能得到这个递归程序的全部求解过程。
代码实现具体查看按思路注释版!
注:值得注意的是函数执行的顺序 和参数的含义。
当然如果只是简单,可以推算出规律(2的n次方-1)不用递归。如下代码便可计算:
#汉诺塔递归算法 2的n次方—1
def h(n): #直接计算
return 2**n-1
print(h(3))
最后输出7.