n阶汉诺塔问题(Hanoi)

问题描述

  • 假设有3个分别命名为X、Y、Z的塔座
  • 在塔座X上插有n个直径大小各不相同、依小到大编号为1,2,...,n的圆盘。
  • 现要求将X轴上的n个圆盘移至塔座Z上并仍按同样顺序叠排
  • 圆盘移动时必须遵循下列规则:
    1. 每次只能移动一个圆盘
    2. 圆盘可以插在X、Y、Z中的任一塔座上
    3. 任何时刻都不能将一个较大的圆盘压在较小的圆盘之上

1275166-20171129085550159-279687979.gif

算法思想

  • 当n=1时
    • 问题比较简单,只要将编号为1的圆盘从塔座X直接移至塔座Z上即可;
  • 当n>1时
    • 需利用塔座Y作辅助塔座,若能设法将压在编号为n的盘之上的n-1个圆盘从塔座X移至塔座Y上
    • 然后将编号为n的圆盘从塔座X移至塔座Z上
    • 最后再将塔座Y上的n-1个圆盘移至塔座Z上
    • 而将n-1个圆盘移至塔座Z上又相当于一个新的汉诺塔问题,这一次是以X为辅助塔座
    • 循环往复,总是以X和Y这两个为辅助塔座
  • 简言之(参考链接
    • 首先以Z为辅助塔座将n-1个圆盘移动Y
    • 将编号为n的圆盘移至塔座Z
    • 再将剩余的n-1个圆盘移至塔座Z

1275166-20171129085513597-203535854.png

C语言伪代码表示的算法

void hanoi(int n, char x, char y, char z){
    // 将塔座x上按直径由小到大且自上而下编号为1至n的n个圆盘按规则搬到
    // 塔座z上,y可用作辅助塔座
    // 搬动操作move(x, n, z)可定义为(c是初值为0的全局变量,对搬动计数):
    // printf("%i. Move disk % i from %c to %c\n", ++c, n, x, z);
    if(n == 1)
        move(x, 1, z);              // 将编号为1的圆盘从x移到z
    else{
        hanoi(n-1, x, z, y);        // 将x上编号为1至n-1的圆盘移到y, z作辅助塔
        move(x, n, z);              // 将编号为n的圆盘从x移到z
        hanoi(n-1, y, x, z);        // 将y上编号为1至n-1的圆盘移到z, x作辅助塔
    }
}

Java

  • 源码
/**
 * 汉诺塔算法实现
 * @param n 圆盘的数量
 * @param x X塔座
 * @param y Y塔座
 * @param z Z塔座
 */
public void hanoi (int n, char x, char y, char z) {
    if (1 == n) {
        move(x, 1, z);
    } else {
        hanoi(n-1, x, z, y);
        move(x, n, z);
        hanoi(n-1, y, x, z);
    }
}

/**
 * 打印出移动过程
 * @param x X塔座
 * @param n Y塔座
 * @param z Z塔座
 */
public static final void move (char x, int n, char z) {
    System.out.println("将编号为" + n + "的圆盘从" + x + "塔座放到" + z + "塔座");
}
  • 测试用例
@Test
public void testHanoi () {
    hanoi (3, 'X', 'Y', 'Z');
}
  • 测试结果
将编号为1的圆盘从X塔座放到Z塔座
将编号为2的圆盘从X塔座放到Y塔座
将编号为1的圆盘从Z塔座放到Y塔座
将编号为3的圆盘从X塔座放到Z塔座
将编号为1的圆盘从Y塔座放到X塔座
将编号为2的圆盘从Y塔座放到Z塔座
将编号为1的圆盘从X塔座放到Z塔座

Python

  • 源码
def move(n, a, b, c):
    if n == 1:
        print a, '-->', c
    else:
        move(n-1, a, c, b)
        print a, '-->', c
        move(n-1, b, a, c)
  • 测试用例
move(3, 'A', 'B', 'C')
  • 测试结果
A --> C
A --> B
C --> B
A --> C
B --> A
B --> C
A --> C

转载于:https://www.cnblogs.com/freelancy/p/7918469.html

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值