您的位置:首页 > 理论基础 > 数据结构算法

数据结构经典算法学习之河内之塔(汉诺塔)

2016-12-28 12:09 393 查看
河内之塔 (汉诺塔)


故事背景:河内之塔(Towers of Hanoi)是法国人M.Claus(Lucas)于1883年从泰国带至法国的,河内为越战时北越的首都,即现在的胡志明市;1883年法国数学家 Edouard Lucas曾提及这个故事,据说创世纪时Benares有一座波罗教塔,是由三支钻石棒(Pag)所支撑,开始时神在第一根棒上放置64个由上至下依由小至大排列的金盘(Disc),并命令僧侣将所有的金盘从第一根石棒移至第三根石棒,且搬运过程中遵守大盘子在小盘子之下的原则,若每日仅搬一个盘子,则当盘子全数搬运完毕之时,此塔将毁损,而也就是世界末日来临之时。

问题描述:

有一个梵塔,塔内有三个座A、B、C,A座上有诺干个盘子,盘子大小不等,大的在下,小的在上(如图)。

把这些个盘子从A座移到C座,中间可以借用B座但每次只能允许移动一个盘子,并且在移动过程中,3个座上的盘子始终保持大盘在下,小盘在上。

描述简化:

把A柱上的n个盘子移动到C柱,其中可以借用B柱。

问题手拆:

设定有n个盘子在A上

则:当n=1,A——>C

        当n=2,A——>B,A——>C,B——>C

        当n=3,A——>C,A——>B,C——>B,A——C,B——>A,B——C,A——>C

        当n=4,A——>B,A——>C,B——>C,A——B,C——>A,C——B,A——>B(至此将顶部3个盘子都移到了B上),A——>C,B——>C,B——>A,C——A,B——>C,A——B,A——>C,B——>C

        当n=5,A——>C,A——>B,C——>B,A——C,B——>A,B——C,A——>C(至此将顶部3个盘子都移到了C上),A——>B,C——>B,C——>A,B——A,C——>B,A——C,A——>B,C——>B(至此将顶部4个盘子都移到了B上),A——>C(这里博主就不往下面写了,交给读者们吧,我脑子有点累。。。思路:此时B上有4个盘子,C上有一个最大的盘子,假设将C上的盘子忽略掉存在,因为它已经是最大的了,上面放任何一个盘子都不会违反规则;至此将B的情景放在上面n=4的那一步中,假设B就是A,那么继续进行,将B的最大盘子放到C上;至此再类推到第二步n=3时...)...........

        当n=....

问题思考:

其实上面的问题,大家经过思考会发现,不管过程如何曲折,想要把A上n个盘子移到C上,就必须要把前n-1个盘子先放到B上,然后将最大的盘子放到C上;之后再将C上的固定了的盘子假设不存在,此刻B上的盘子当做上一步的A盘子,继续一样的思路进行(其实仔细看上面的问题手拆,会发现规律,前几步都是重复的,后几步其实只是把A换成了B或者A换成了C)。另外可能网上许多的类似关于汉诺塔的解释方法,都没有详细多少如何把n-1个盘子放到B上呢?其实给大家提供一个解决思路:想要将n-1个盘子放到B上,那就必须先将n-2个盘子移到C处,再将最大的盘子从A移到B处。其实说白了仍然是汉诺塔的递归)

代码实现(网上有很多一样的大致实现,但都是一个思路的实现,具体到函数层的实现并没有写,博主这里有时间给大家写一个做参考,暂时先放个雷同的吧):

public void hanoi(String A, String B, String C, int n) {
if (n == 1) {
System.out.println("这个简单,直接将" + A +"的"+n+"个盘子移动到" + C + "!");
} else {
hanoi(A, C, B, n - 1);
System.out.println("将" + A +"的"+n+"个盘子移动到" + C + "!");
hanoi(B, A, C, n - 1);

}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息