汉诺塔简介

最近在看数据结构和算法,遇到了一个非常有意思的问题——汉诺塔问题。

先看下百度百科是怎么定义汉诺塔的规则的:

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

额,好吧,好像有点啰里啰嗦的。其实一句话就是,在三个柱子之间移动盘子,一次只能移动一个,并且要保证每一步上边的盘子都要比下边的盘子小,最终实现把所有的盘子都从最左边柱子移动到最右边的柱子上。

我找了一个小游戏,可以玩一下,体验一下这个过程。相信我,你玩不过第五关的!嘿嘿,玩不过再过来看一下,我是怎么给你做游戏攻略(作弊)的。

地址:http://www.4399.com/flash/109504_1.htm

我相信,有很多童鞋在学递归的时候,都会受到这个问题的困扰。别着急,你不是一个人,我第一次看到这个也是一脸懵逼,这什么鬼啊,这么复杂。下面我通过图解的方式,演示整个移动过程,帮助你理解用递归解决这个问题的思想。

汉诺塔图解

我们一步一步从简单到复杂。为了方便,我把三个柱子从左到右分别叫 A,B,C。盘子的数字从上到下依次增大。

一个盘子

只有一个盘子的时候,就比较简单了。如图,只需要一步,直接把 第 1 个盘子从 A移动到 C就完成了。

两个盘子

两个盘子的时候,也比较简单,如下图,只需要借助一下 B 柱子即可完成。

这个过程可以表述为:

把第1个盘子从A移到B
把第2个盘子从A移到C
把第1个盘子从B移到C

三个盘子

三个盘子的时候,稍微复杂一些,但是我们一般也是可以通过心算,把过程推演出来的。

把第1个盘子从A移到C
把第2个盘子从A移到B
把第1个盘子从C移到B
把第3个盘子从A移到C
把第1个盘子从B移到A
把第2个盘子从B移到C
把第1个盘子从A移到C

n 个盘子

铛铛铛,现在到了第四关了,我相信已经有部分小伙伴感觉开始吃力了,通过演算就不好搞了。如果你搞不出来,我们就借助计算机来帮我们推算出来这个过程(哈哈,我是不是很机智)。

其实,通过前面的三个例子,我们可以发现,盘子的移动是有规律可循的。

细心的你有没有发现,在每一步盘子移动的过程中,总会有一步,是下边最大的盘子,从 A 移到 C 的。如,两个盘子,就是第 2 个盘子从 A移到 C,三个盘子,就是第 3 个盘子从 A 移到 C。

仔细观察,以三个盘子为例,把第 3 个盘子从 A 移动到 C 这一步,其实,第 1 个和第 2 个盘子是已经按顺序摆放好了的,即一起放在中间的 B 柱子。

因此,我们可以把这个动作抽象出来,把除了最下边的盘子之外的其他盘子看成一个整体。这样的话,整个流程,就和两个盘子的移动过程没什么两样了。总共就三步,我以四个盘子为例。看以下动画,

整个过程可以表述为:

把1,2,3盘子整体从 A 移到 B (可以认为是借助 C 柱子移动的),
把第 4 个盘子从 A 移到 C(不需要借助额外的柱子),
把1,2,3盘子整体从 B 移到 C(借助 A 柱子)

但是,这只是我们把它抽象出来的过程,游戏中不允许我们整体移动,怎么办呢。

好说,我把 1,2,3 这个整体再拆分,不就是三个盘子的移动过程嘛。完全可以把 1,2看成一个整体一起移动,3 单个移动,也是三步完成。然后再拆分,直到只有最后一个盘子的时候,就完成了整个过程。

所以,可以看到,这个拆分的过程,就是不断递归的过程。而每次递归时,都可以把第 1 个盘子到 第 n-1 个盘子看成一个整体。每一次递归都是一个三步曲,借助另外一个柱子,从当前柱子移动到目标柱子。看代码,

public class HanioTest {public static void main(String[] args) {int n = 4;char a = 'A',b = 'B',c = 'C';hanio(n,a,b,c);}/*** * @param n  一共需要移动的盘子* @param a  盘子移动的起始柱子* @param b  借助的柱子* @param c  盘子需要移动到的目标柱子*/public static void hanio(int n,char a, char b, char c){//只有一个盘子的时候,就直接从A移到Cif(n == 1){move(n,a,c);}else{//三步曲,注意观察,a,b,c三个的位置变化//1.把 n-1 个盘子看成一个整体,借助 C 从 A 移动到 Bhanio(n-1,a,c,b);//2.把第 n 个盘子从 A 移动到 Cmove(n,a,c);//3.再把 n-1 盘子整体,借助 A 从 B 移动到 Chanio(n-1,b,a,c);}}public static void move(int n , char a, char b){System.out.println("把第"+ n +"个盘子从"+ a +"移到"+ b);}
}

聪明的你,如果游戏第四关通关了,可以用来检查一下这个代码执行过程是否和你的移动过程一致。

第五关,如果你不借助程序,能心算出来,我只能说你太厉害了,I 服了 YOU,佩服佩服。

那么第六关,第七关呢。

结语

回到最开始,百度百科说要移动 64 片黄金圆盘,OMG 的,如果谁能手动计算出来,那才是真的大神(不过,话说,谁会这么无聊呢,哈哈)。

感兴趣的你也可以尝试用程序跑一遍 64 片是什么结果,我估计就算你机器性能很好,也得跑好长时间。。。

温馨提示:机器炸了不怪我哦 ~

个盘子的汉诺塔需要移动几步_图解汉诺塔问题( Java 递归实现)相关推荐

  1. 个盘子的汉诺塔需要移动几步_看漫画学C++039:递归解汉诺塔

    点击蓝字 关注我们 本话内容 请输入 相传在古印度圣庙中,有一种被称为汉诺塔(Hanoi)的游戏.该游戏是在一块铜板装置上,有三根杆(编号A.B.C),在A杆自下而上.由大到小按顺序放置64个金盘(如 ...

  2. 个盘子的汉诺塔需要移动几步_坨——理解递归实现quot;汉诺塔quot;代码的关键...

    我记得,大学学C语言时,在函数递归调用那一节有个作业,就是写汉诺塔.不少同学遭遇到困难.在知乎上遇见的就有: 如何理解汉诺塔的递归?​www.zhihu.com 题主发出悲鸣:"--学C++ ...

  3. 汉诺塔问题递归算法python代码_[python]汉诺塔问题递归实现

    一.问题描述及算法步骤 汉诺塔问题的大意是有三根柱子a, b, c,现在a柱有N个盘子从下往上尺寸递减排列,要求: 1. 将a上的盘子移动到c柱上; 2. 每次移动一个盘子; 3. 柱子上的盘子始终必 ...

  4. C语言入门递归算法——汉诺塔(简单易懂,最后还有汉诺塔游戏)

    什么是汉诺塔: 汉诺塔:(又称河内塔)问题是源于印度一个古老传说的益智玩具.大梵天创造世界的时候做了三根金刚石柱子,在一根柱子上从下往上按照大小顺序摞着64片黄金圆盘.大梵天命令婆罗门把圆盘从下面开始 ...

  5. 汉诺塔(hanoi)、双色汉诺塔(分离型)、三色汉诺塔

    汉诺塔 汉诺塔(Towers of Hanoi)是法国人M.Claus(Lucas)于1883年从泰国带至法国的,河内为越战时北越的首都,即现在的胡志明市:1883年法国数学家Edouard Luca ...

  6. 图解汉诺塔问题(递归求解)

    汉诺塔:汉诺塔(Tower of Hanoi)源于印度传说中,大梵天创造世界时造了三根金钢石柱子,其中一根柱子自底向上叠着64片黄金圆盘.大梵天命令婆罗门把圆盘从下面开始按大小顺序重新摆放在另一根柱子 ...

  7. 图解汉诺塔,用Python实现经典递归

    感谢漂流的云的图解汉诺塔问题(递归求解) (1)先从最简单的模型开始,假如A柱有2个盘,我们的任务是把这两个盘按照规则(小叠在大上)移到C柱.操作步骤如下所示: (2)现在把原始时A柱盘子数增加到10 ...

  8. 图解汉诺塔(满屏幕都是图)

    图解汉诺塔(满屏幕都是图) 汉诺塔问题 步骤1: 步骤2 步骤3: 技术总结 和很多人一样,我刚刚接触汉诺塔的时候,可能说是头晕目眩,立马放弃. 但如果用图形表示感觉会好很多. 以下是我的学习思路: ...

  9. java递归实现汉诺塔

    汉诺塔的规则是:一共三根柱子,一根柱子从上到下套着有小到大的若干个圆盘,要将所有圆盘按照这个排放顺序移动到第三根柱子上,并且每次只能移动一个圆盘. 可以将整个过程分为三个步骤来看: 第一步:将除最大圆 ...

最新文章

  1. Oracle中查看表空间的使用率的脚本
  2. 初学PHP:用post传递checkbox
  3. BFC与IFC概念理解+布局规则+形成方法+用处
  4. 业务处理速度变慢?且看IT如何成为救世主
  5. 【转】spin_lock、spin_lock_irq、spin_lock_irqsave区别
  6. Hive静态分区表动态分区表
  7. hr妹子招聘黑话,面试的时候小心了!
  8. 【Linux】Linux 守护进程的启动方法
  9. php 原子性,PHP下O_APPEND模式的原子性
  10. QuickWebApi2:使用Lambda方式,完成对WebApi的开发和调用-文档的生成
  11. 理想的工作永远不存在
  12. bool类型转int, 或者bool数组对象转int/float数组对象
  13. OAuth 2.0 开放授权的那些事儿
  14. go import导入包详解
  15. Anaconda 更换浏览器要求输入token
  16. java文件上传过滤,struts2中文件上传过滤
  17. 基于Java+SpringBoot+Thymeleaf+Mysql校园运动场地预约系统设计与实现
  18. Spring AOP实现原理,从代理说起
  19. 从多个Word文件中取值到Excel中,整理文件的神器,Word精灵V7.3
  20. Android ART dex2oat 加载加速浅析

热门文章

  1. R语言plotly可视化:可视化直方图、归一化的直方图、水平直方图、互相重叠的直方图、堆叠的直方图、累积直方图、通过bingroup参数设置多个直方图使用相同的bins设置、自定义直方图条形的间距
  2. pandas获取dataframe数据列的数据类型、获取dataframe每类数据类型数据列的个数、使用select_dtypes函数、include参数以及exclude参数按照数据类型筛选数据
  3. 框架+重量级+轻量级
  4. mysql5.0入门_MySQL 5.0基础的基本内容的介绍
  5. JAVA编程TXT文件_java开发之读写txt文件操作的实现
  6. JAVA基础3-选择语句
  7. 上升沿_不懂上升、下降沿的我,高兴惨了!
  8. python 判断列表list是否为空
  9. ubuntu18.04上安装ffmpeg
  10. 【Three.js】关于Three.js的辅助库ststs.js报错的解决方案