作为一个Java初学者,看韩顺平老师的递归那一段,提到了汉诺塔的问题,但是大家普遍感到困惑,尤其是韩老师讲到的“借助”这个词,让不少同学感到无法理解。

实际上,借助在三行移动的代码里已经体现了,只是这个词让人以为要额外做些什么。下面我结合自己对代码的运行分析,记录一下自己的理解和体会。

public class Main {public static void main(String[] args) {Tower t = new Tower();t.move(4, 'a', 'b', 'c');}
}class Tower {/*move方法的含义a为起始柱,c为目标柱,b为第三柱*/void move (int plateNum, char a, char b, char c) {if (plateNum == 1) {System.out.println(a + "->" + c);} else {move (plateNum -1, a, c, b);System.out.println(a + "->" + c);move (plateNum -1, b, a, c);}}
}

上面的代码,是韩顺平老师的原始代码。起初我也看得很懵,为了更好地观察,我想到加入一些输出语句,以观察递归的调用情况。

public class Main {public static void main(String[] args) {Tower t = new Tower();t.move(4, 'a', 'b', 'c');}
}class Tower {/*move方法的含义a为起始柱,c为目标柱,b为第三柱*/void move (int plateNum, char a, char b, char c) {if (plateNum == 1) {System.out.println(a + "->" + c);} else {System.out.println("==move" + (plateNum -1)+ "个从"+ a +"到"+ b +":");move (plateNum -1, a, c, b);System.out.println((plateNum -1)+ "个从"+ a +"到"+ b +"完成:==");System.out.println();System.out.println(a + "->" + c);System.out.println();System.out.println("==move" + (plateNum -1)+ "个从"+ b +"到"+ c +":");move (plateNum -1, b, a, c);System.out.println((plateNum -1)+ "个从"+ b +"到"+ c +"完成:==");System.out.println();}}
}

大家可以看到,我在move方法上面有一小段注释:

/*move方法的含义
      a为起始柱,c为目标柱,b为第三柱
    */

这段话的意思,我觉得很关键,至少对我本人来说是这样。因为汉诺塔的问题,一开始就定下了说要把所有的圆盘从a移动到c。所以一开始可能就觉得,a和c有什么特殊之处,而b又被看作被"借助"的一根柱子,其实不用这么看。这个问题的意思无非就是把一个东西从一个地方移动到另一个地方。有起点有终点,至于起点是a/b还是c,根本不重要。所以move这个函数就是说,输入圆盘数,三根柱子,圆盘现在在其中一根柱子上,现在要全部移动到另一根柱子上,就完了。理解这一点很重要,因为move递归的过程中,本质就是大目标move反推出中目标move、小目标move,大目标分割成很多个中目标,中目标分割成很多个小目标,移动圆盘的过程中,对不同的目标move来说,起点和终点都是不一样的,所以abc完全是平等的。但是,在实现move方法的过程中,我们是人为在规定哪个形参代表什么柱子(起点终点)的。这样调用的时候才知道如何传参。我们规定说,a代表我们想要移动的圆盘当前的位置,c代表它的目标位置,b是第三根。

其实,也完全可以这么写:

void move (int plateNum, char start, char third, char dest) {if (plateNum == 1) {System.out.println(start + "->" + dest);} else {move (plateNum -1, start, dest, third);System.out.println(start + "->" + dest);move (plateNum -1, third, start, dest);}}

start 是当前所在柱,dest是目标柱,third是另一根柱子。

好了,参数就解释到这里。下面看上面的代码输出情况:

{==move3个从a到b:
[==move2个从a到c:
(==move1个从a到b:
a->b
1个从a到b完成:==)a->c(==move1个从b到c:
b->c
1个从b到c完成:==)2个从a到c完成:==]a->b[==move2个从c到b:
(==move1个从c到a:
c->a
1个从c到a完成:==)c->b(==move1个从a到b:
a->b
1个从a到b完成:==)2个从c到b完成:==]3个从a到b完成:==}a->c{==move3个从b到c:
==move2个从b到a:
==move1个从b到c:
b->c
1个从b到c完成:==b->a==move1个从c到a:
c->a
1个从c到a完成:==2个从b到a完成:==b->c==move2个从a到c:
==move1个从a到b:
a->b
1个从a到b完成:==a->c==move1个从b到c:
b->c
1个从b到c完成:==2个从a到c完成:==3个从b到c完成:==}

为了方便表示结构,我在前一半段中,将目标 手动用加了括号括起来,大目标用“{}”,中目标用"[]",小目标用“()”。

大家可以看到 整个move四个圆盘的总目标,被分成了两个【移动3个圆盘的大目标】(外加一个移动最底下圆盘的目标),然后移动3个圆盘的目标,又被分成了两个【移动2个圆盘的中目标】,移动2个圆盘的目标又被分成了两个【移动1个圆盘的中目标】。

其实这就是递归最直接的体现。为什么简单四行代码就解决了所有问题,因为圆盘数再多,也都是这几行代码叠加出来的。所以实现这个递归,只要实现一个圆盘的移动和两个圆盘的移动就可以了。所以,起初,我们的代码应该是这样的:

void move (int plateNum, char a, char b, char c) {if (plateNum == 1) {System.out.println(a + "->" + c);} else if (plateNum == 2){System.out.println(a + "->" + b);System.out.println(a + "->" + c);System.out.println(b + "->" + c);}}

但是为了实现递归,我们需要将移动2个圆盘的操作进行 “范化”,其它可以用于其它任何数字的圆盘。所以,把plateNum == 2直接去掉,其它的也都用move函数来“范化”,就实现了递归。

void move (int plateNum, char a, char b, char c) {if (plateNum == 1) {System.out.println(a + "->" + c);} else {move (plateNum -1, a, c, b);System.out.println(a + "->" + c);move (plateNum -1, b, a, c);}}

最后,再回到一开始提到的那个问题,“借助”b是如何借助的,就是这三行带来的结果,只是范化后就容易看出来了。

System.out.println(a + "->" + b);System.out.println(a + "->" + c);System.out.println(b + "->" + c);

汉诺塔问题 Java详解相关推荐

  1. java汉诺塔(含汉诺塔问题的详解)

    目录 一:汉诺塔问题 二:汉诺塔问题思路 三:图示化思路 四:代码展示 一:汉诺塔问题 汉诺塔问题是一个经典的问题.汉诺塔(Hanoi Tower),又称河内塔,源于印度一个古老传说.大梵天创造世界的 ...

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

    目录 一.介绍 二.游戏规则 三.玩法简介 四.算法分析 五.代码解析 六.源码 七.递归过程详解 一.介绍 汉诺塔(Tower of Hanoi),又称河内塔,是一个源于印度古老传说的益智玩具.大梵 ...

  3. 汉诺塔代码图文详解(递归入门)

    游戏规则: 已知条件 存在A,B,C三根柱子,A上套有N片圆盘 (如下图) 目的 将A上的所有圆盘移到C上 约束条件 每次只能移动一片圆盘,且整个过程中只能出现小圆盘在大圆盘之上的情况 首先我们模拟( ...

  4. C语言汉诺塔问题图文详解

    设立三根柱子,pos1,pos2,pos3 要求将pos1柱子上的三个圆盘按照顺序移动到pos3柱子上,并且每次只能移动一个圆盘,移动过程中每个柱子上的圆盘都保持下大上小的顺序排列 当只有一个圆盘时, ...

  5. 汉诺塔算法 java_汉诺塔算法java实现详解

    import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; public ...

  6. 经典汉诺塔(Java初学递归篇)

    大一学C的时候已经接触到汉诺塔递归的问题,当时只是简单了解过方法,最近开了算法课,打算重新捋一捋. 题目描述:         有三根柱子分别为A.B.C,柱子A上从下到上按金字塔状叠放着n个不同大小 ...

  7. 汉诺塔(java版)

    汉诺塔原理 汉诺塔规则:有A.B.C三根柱子,设汉诺塔层数为N,则最底最大的一个盘数便是N.例如下图有三层则N=3,我们只需将A柱上(1-N)个盘全部移至B柱或C柱上即可(挪动盘时,N值大的必须放在N ...

  8. 汉诺塔问题java编程,Java经典编程300例之实例047 汉诺塔问题求解(递归)

    实例说明 汉诺塔问题的描述如下:有A.B和C 3跟柱子,在A上从下往上按照从小到大的顺序放着64个圆盘,以B为中介,把盘子全部移动到C上.移动过程中,要求任意盘子的下面要么没有盘子,要么只能有比它大的 ...

  9. 汉诺塔模拟器java

    游戏规则:百度百科 技巧: import java.util.LinkedList; import java.util.Scanner;public class 汉诺塔模拟器 {LinkedList& ...

最新文章

  1. 机器学习中的模型评价、模型选择及算法选择
  2. 卧槽!微软Python入门课居然汉化了!
  3. java isfocusowner_Java JTextArea.isFocusOwner方法代码示例
  4. Linux环境安装Kafka2.6.0
  5. HDFS修改副本数并生效
  6. 安卓耗电监控app_Android系统十大耗电应用拍照APP排第一
  7. C#调用C++DLL传递结构体数组的终极解决方案
  8. 数学知识在游戏中的运用
  9. oracle中主键创建的语法,Oracle中主键、外键、索引、序列、唯一性约束的创建
  10. 白板机器学习笔记 P60-P65 EM算法
  11. react组件卸载调用的方法_react相关基础知识
  12. 安装python版opencv遇到ModuleNotFoundError: No module named ‘skbuild‘
  13. 兄弟Brother DCP-1519 驱动
  14. 苹果Mac怎样切换大写输入法?
  15. 炸!撩下 OLAP 数据分析的黑马神器 ClickHouse
  16. 东周科目三考场5号线_光明东周科目三考场,5条道图纸心得分享
  17. 怎么画一点透视,两点透视,三点透视
  18. 大家都在学Python,你和别人的差距在哪?
  19. MFC添加界面的背景图片方法总结
  20. 一个屌丝程序猿的人生(三十八)

热门文章

  1. 个人角度阐述IPTV电视和有线电视的不同
  2. Source Insight4的使用以及下载
  3. 解除Win10网速限制
  4. 计算机类可以去烟草吗,“铁饭碗”中国烟草春招开启!年薪10万+社会在职、专科可报...
  5. setup,ref,reactive
  6. tcping.exe - 通过tcp连接ping
  7. SQL注入-HTTP头的一些注入
  8. 专题测试02·一元函数微分学【李艳芳全程班】
  9. 每日学术速递5.27
  10. Java: Pattern 类与 Matcher 类