小言_互联网的博客

递归经典例题 --- 汉诺塔(图文详解)

338人阅读  评论(0)

目录

一、介绍

二、游戏规则

三、玩法简介

四、算法分析

五、代码解析

六、源码

七、递归过程详解


一、介绍

汉诺塔(Tower of Hanoi),又称河内塔,是一个源于印度古老传说的益智玩具。大梵天创造世界的时候做了三根金刚石柱子,在一根柱子上从下往上按照大小顺序摞着64片黄金圆盘。大梵天命令婆罗门把圆盘从下面开始按大小顺序重新摆放在另一根柱子上。并且规定,在小圆盘上不能放大圆盘,在三根柱子之间一次只能移动一个圆盘。

                                                                                                                             ---- 摘抄百度

二、游戏规则

把A杆上的盘子全部移到C杆上,并仍保持原有顺序叠好。

操作规则:每次只能移动一个盘子,并且在移动过程中三根杆上都始终保持大盘在下小盘在上,操作过程中盘子可以置于A(起始柱)、B(辅助柱)、C(目标柱)任一杆上。 

三、玩法简介

假设有三个盘子,全部都要移动到C(如下图)

 根据汉诺塔的游戏规则,首先需要把3号盘子和2号盘子分别向B和C移动(如下图)

 接着把3号盘子移动到B,再1号盘移动到C,此时最大的盘子已经到C的底部了(如下图) 

 接着把3号盘子移动到A,然后把2号盘子移动到C(如下图)

最后把3号盘子移动到C(如下图),游戏就成功了!

四、算法分析

假设有n个盘子,来分析其规律

①当n = 1时,A只有1个盘子,可以很轻易地将它移动到C上

②当n = 2时,A有2个盘子

其移动过程,先把A中2号盘子移动到B中暂存

 再把A中1号盘子移动到C

 最后把B中2号盘子移动到C

③ 当n = 3时

玩法简介讲过了。

总结:

通过分析以上三种情况的移动思路,小伙伴发现一个规律没有,对于n个盘子的汉诺塔问题,移动圆盘的过程是:

1.都是将起始柱(A)上的n-1(除最大盘子外)个圆盘移动到辅助柱(B)上。  

2.再将起始柱(A)上遗留的(最大盘子)1个圆盘移动到目标柱(C)上。  

3.最后将辅助柱(B)上所有的圆盘移动到目标柱(C)上。        

要解决n层汉诺塔,就必须解决n-1的汉诺塔。由此,n 个圆盘的汉诺塔问题就简化成了 n-1 个圆盘的汉诺塔问题,把一个复杂的问题简单化,这就是递归

五、代码解析

首先写出主函数的内容


  
  1. #include <stdio.h>
  2. int main()
  3. {
  4. int n = 0; //n代表盘子个数
  5. //输入盘子的个数
  6. scanf( "%d", &n);
  7. //写出函数
  8. Hanno_Tower(n, 'A', 'B', 'C');
  9. return 0;
  10. }

根据上面的总结分析

调用函数部分:

当n=1时,直接移动到C(目标柱)就行了


  
  1. void Hanno_Tower(int n, char A, char B, char C)
  2. {
  3. if (n == 1)
  4. {
  5. printf( "将编号为%d的盘子从%c柱子移动到%c柱子上\n", n, A, C);
  6. }
  7. }

当n>1时,首先要把起始柱(A)上的n-1(除最大盘子外)个圆盘移动到辅助柱(B)上

这时就要再次调用Hanno_Tower函数


  
  1. void Hanno_Tower(int n, char A, char B, char C)
  2. {
  3. if (n == 1)
  4. {
  5. printf( "将编号为%d的盘子从%c柱子移动到%c柱子上\n", n, A, C);
  6. }
  7. else
  8. {
  9. Hanno_Tower(n - 1, A, C, B); //将n-1个盘子,从A绕过C移动到B
  10. }
  11. }

再将起始柱(A)上遗留的(最大盘子)1个圆盘移动到目标柱(C)上


  
  1. void Hanno_Tower(int n, char A, char B, char C)
  2. {
  3. if (n == 1)
  4. {
  5. printf( "% c-> % c\n",A, C);
  6. }
  7. else
  8. {
  9. Hanno_Tower(n - 1, A, C, B); //将n-1个盘子,从A绕过C移动到B
  10. printf( "将编号为%d的盘子从%c柱子移动到%c柱子上\n", n, A, C); //将起始柱上遗留的1个圆盘移动到目标柱上
  11. }
  12. }

最后将辅助柱(B)上所有的圆盘移动到目标柱(C)上。 


  
  1. void Hanno_Tower(int n, char A, char B, char C)
  2. {
  3. if (n == 1)
  4. {
  5. printf( "% c-> % c\n",A, C);
  6. }
  7. else
  8. {
  9. Hanno_Tower(n - 1, A, C, B); //将n-1个盘子,从A绕过C移动到B
  10. printf( "% c-> % c\n",A, C); //将起始柱上遗留的1个圆盘移动到目标柱上
  11. Hanno_Tower(n -1, B, A, C); //把在B中剩余的n-1个盘子,从B绕过A移动到C
  12. }
  13. }

六、源码


  
  1. #include <stdio.h>
  2. void Hanno_Tower(int n, char A, char B, char C)
  3. {
  4. if (n == 1)
  5. {
  6. printf( "将编号为%d的盘子从%c柱子移动到%c柱子上\n", n, A, C);
  7. }
  8. else
  9. {
  10. Hanno_Tower(n - 1, A, C, B);
  11. printf( "将编号为%d的盘子从%c柱子移动到%c柱子上\n", n, A, C);
  12. Hanno_Tower(n - 1, B, A, C);
  13. }
  14. }
  15. int main()
  16. {
  17. int n = 0;
  18. scanf( "%d", &n);
  19. Hanno_Tower(n, 'A', 'B', 'C');
  20. return 0;
  21. }

七、递归过程详解

假设只有2个盘子

n = 1继续调用函数,但这里要注意,图三n = 1时,此时char A存放的是A, char B存放的是C,char C存放的是B,执行if语句,所以首先会先打印“将编号为1的盘子从A柱子移动到B柱子上”

接下来开始回归(红线)

n = 2 ,接下来会在屏幕上打印“将编号为2的盘子从A柱子移动到C柱子上”

最后调用Hanno_Tower(n - 1, B, A, C);接下来继续用图来帮助大家分析

  如图三所示,n = 1,执行if语句,此时char A存放的是B,char B存放的是A,char C存放的是C,所以最后就会打印“将编号为1的盘子从B柱子移动到C柱子上”

所以当n = 2时,程序是否能打印以上结果呢?

 显然符合我们的预期!!


转载:https://blog.csdn.net/Weraphael/article/details/127866850
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场