河内塔问题(Hanoi Tower)

学习程序设计,必练河内塔问题。好的分析、实现,对于初学者有些帮助。


说明:

  • 采用Java源代码风格;
  • 采用doxygen风格的注释(也是Javadoc风格的注释);
  • 为了输出美观,加了tabs,pLineNumber两个参数,让代码有点复杂了。但鉴于输出的美观也很重要,保留了这个复杂性。

/**
 * $Id$
 * wanzijin, 2014-05-09
 */
#include 
  
  
   
   
#include 
   
   
    
    

/**
 * 河内塔问题求解(递归:中序遍历二叉树)
 *
 * @param pLineNumber 输出行号;
 * @param tabs 缩进级别:用于控制输出的“缩进”量,纯美观设计,初学者可忽略它;
 *                递归树的根缩进量为0,每下一层,则缩进量加8,在标准输出上可以得到比较美观的效果;
 * @param n 要移动的盘子个数,定义域为非负整数,请尽量在[0,20]之间取值;
 *                n大于20的话,系统会表示负担很重,这与国际象棋盘上放谷粒的故事一个道理;-)
 * @param a 源柱子,定义域为{'a','b','c'}
 * @param b 中间柱子,定义域为{'a','b','c'}
 * @param c 目标柱子,定义域为{'a','b','c'}
 *
 * @inv     缩进级别与递归层级的和(tabs+n);
 * @inv     {a,b,c}=={'a','b','c'}
 */
void hanoi_move(int *pLineNumber, int tabs, int n, char a, char b, char c)
{
    if (n<2)
    {
        if(n==1)
        {
            // 只有一个盘子:直接搬到目标柱子上
            printf("%4d,%*d:%c->%c\n",++pLineNumber[0],tabs*8,n,a,c);
        }
        return;
    }

    // 先把源柱子上的n-1个盘子搬到中间柱子上
    hanoi_move(pLineNumber,tabs+1,n-1,a,c,b); 
    // 再把源柱子上的第n个盘子搬到目标柱子上
    printf("%4d,%*d:%c->%c\n",++pLineNumber[0],tabs*8,n,a,c);
    // 最后把中间柱子上的n-1个盘子搬到目标柱子上
    hanoi_move(pLineNumber,tabs+1,n-1,b,a,c);          
}

int main(int argc, const char *argv[])
{
    int n,lineNumber=0;

    if (argc<2)
    {
        // 教科书上很喜欢用scanf(),UNIX风格的“管道”、“重定向”等机制,也主张多用标准输入
        printf("Input:");
        scanf("%d",&n);
    }
    else
    {
        // 从单个“工具”角度,用“命令行参数”真心方便
        // 取第二个命令行参数(命令名本身是第一个)
        n = atol(argv[1]);
    }

    hanoi_move(&lineNumber,0,n,'A','B','C');
    return 0;
}

   
   
  
  

输出实例:

e:\home\wzj\hanoyi\Debug>hanoyi 5
argv[0]=hanoyi
argv[1]=5
   1,                               1:A->C
   2,                       2:A->B
   3,                               1:C->B
   4,               3:A->C
   5,                               1:B->A
   6,                       2:B->C
   7,                               1:A->C
   8,       4:A->B
   9,                               1:C->B
  10,                       2:C->A
  11,                               1:B->A
  12,               3:C->B
  13,                               1:A->C
  14,                       2:A->B
  15,                               1:C->B
  16,5:A->C
  17,                               1:B->A
  18,                       2:B->C
  19,                               1:A->C
  20,               3:B->A
  21,                               1:C->B
  22,                       2:C->A
  23,                               1:B->A
  24,       4:B->C
  25,                               1:A->C
  26,                       2:A->B
  27,                               1:C->B
  28,               3:A->C
  29,                               1:B->A
  30,                       2:B->C
  31,                               1:A->C


  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值