Hanoi Tower

Document Sample
Hanoi Tower Powered By Docstoc
					第一章 汉诺塔问题                                          1




                第一章     汉诺塔问题

1.1. 问题描述
1.1.1 题目内容
       用一个递归算法建立程序,实现汉诺塔问题的圆盘的移动。

1.1.2 基本要求
        在这个汉诺塔问题中, 假设有三个分别命名为 A, B 和 C,在塔座 A 上插有 n 个
    直径大小各不同的圆盘。  要求将 A 轴上的 n 个圆盘移至塔座 C 上并任按同样顺序叠
    排,圆盘移动时必须遵循以下规则:1.每次只能移动一个圆盘;2.圆盘可以在 X, Y
    和 Z 中的任意塔座上;3.任何时候都不能将一只较大圆盘压在较小的圆盘之上。最
    后输出移动的步骤以及移动的起始位置。

1.1.3 待测试数据
       该程序输入数据比较单一,为整型,可将待测试数据设置为 2、3、4、5、6。

1.2. 需求分析
1.2.1 程序所能达到的基本功能
       汉诺塔盘座的数量是固定的,用户可以自己确定盘的数量(1 ~~n )。在
    用户确定数量之后,程序开始自动运行(移动圆盘),并依次打印出移动的步数与路
    线,运行结束。

1.2.2 输入形式和输出值的范围
       输入数据为整型数据,设定圆盘的数量,输出跟踪的步数也应为一个整型数据。

1.2.3 输出的形式
       将步数和移动的位置逐个输出形成一个序列。

1.2.4 测试数据要求
       输入数据为整型,且不要过大,否则运算量会很大并且没有多大的实际意义。


1.3. 概要设计
1.3.1 主程序流程及模块调用关系
        主程序流程图见下页:
第一章 汉诺塔问题                                                     2



         主程序流程图:


                             开始



                          输入圆盘数 i




                  i =1       判断 i

                                    i>1

                            递归移
                            动圆盘




                            结束
                            程序

                           图 1-1    主程序流程


         模块调用关系图:


                              主程序




                                            结
                   输               实        果
                   入               现        输
                   模               模        出
                   块               块        模
                                            块


                           图 1-2   模块调用关系


1.3.2 核心粗线条伪码算法
         Algorithm Tower( val   m      <number of disk>
                           val A, B, C <metadata>
                           ref   i     <metadata>         )
      1.    n=m          //输入一个整型数字以设定圆盘的数量
第一章 汉诺塔问题                                                                  3


      2.     if (i =1 )
                1. mov(A, C)       // Base Case 的处理
       3.   else                   // 递归调用的方法处理 General Case
                1. tower(n-1, A,     C, B )
                2. mov (A, C)
                3. tower(n-1, B,   A, C)
       4.   end if
          End Tower


1.4. 详细设计
1.4.1 每个操作的伪码算法
       设计一个成员函数,命名为 move_disk( ),其中设置两个形参 char src 和 char dst
    分别表示两个塔盘 A 和 C。这个函数中,只做 src===dst 操作,同时使 i 的值增加
    1,即用语句 i=i++。
       void towers(int n, char src, char mid, char dst)
       { // 在该成员函数中,n, src, mid, dst 分别表示圆盘的个数与三个塔盘
               If (n==1)
                    {调用 move_disk 函数}
               Else
               towers(n-1,src,dst,mid);                         将
                                                //以 dst(C 塔)为辅助, 1 到 n-1 号圆盘全
               部移动到 mid(B 塔)上
               move_disk(src, dst);               //直接将 A 塔上的圆盘移动到 C 盘上
               towers(n-1, mid, src, dst); //将 B 塔上的 1 至 n-1 号盘移动至 C 塔上
               }

1.4.2 函数调用关系
       在主函数中,设定一个整型变量 disk 以用来向成员函数中传递参数做为圆盘的
    数量,然后直接调用以上函数。再用
       while(n=='y'||n=='Y')
               { 直接调用以上函数 }
    设定一个是否需要重复运行的功能。最后程序结束,设置结束界面 。


1.5. 调试分析
1.5.1 设计与调试过程中遇到的问题及分析、体会
        (1). 关于 Base case 的调用问题
             在开始时,根据程序的概要设计,分别在 Hanoi 类中写了 Base Case 和
       General Case 两个功能函数,   move_disk( )与 towers( )。然后再在主程序中分别对
       这两个函数进行调用,出现了第一个问题,例如当输入圆盘个数为 3 时,圆盘
       只移动了五次,如图 1-3 所示,画图跟踪,其结果是错误的。经过多次的分析
       调试,最后在 towers( )函数中先调用 move_disk( )操作,然后在主函数中只对
       towers( )进行调用,得到了正确的结果如图 1-4 所示。分析可知,这个错误的出
       现主要是对 Base Case 的理解上没有做好,           只要深刻理解了 Base Case 和 General
第一章 汉诺塔问题                                                       4


      Case 的意义和关系,再利用递归思想便能很好的掌握了。




             图   1-3                      图   1-4
       (2). 输入数据的合法性的处理
            程序大体完成后,开始了考虑输入数据的合法性的处理,在程序中,输入
      数据很简单,   就只有一个整型数据 disks 首先限定其范围,限定在 1 到 15 之间,
      因为数据过大没有多大的意义,且运算时间很长(15 个圆盘需移动的步数已达
      32767 之多)。然而当输入数据不是数字时,便出现了死循环如图 1-5 所示。




                                  图 1-5


       经过多次分析,调试与尝试,用各种自己知道的方法如强制转换等都没有能够
       解决,还待进一步思考……
1.5.2 主要和典型算法的时间复杂度的分析
       Hanoi 塔问题中 General Case 调用 Base Case,主要计算程序语句为:
              towers(n-1,src,dst,mid);        move_disk(src, dst);
              towers(n-1, mid, src, dst);
       由计算可得时间复杂度为                    O(n) = 2^n-1.

1.6. 使用说明
     程序开始运行在屏幕上输出“Welcome To Hanoi Game!”欢迎字样,此时不可
   操作,当欢迎字样结束后,程序自动进入可操作界面,此时屏幕显示提示信息,要
   用户输入圆盘数量信息,如图 1-6 所示。程序要求用户输入一个受限制的数 1~15,
   因为数字过大运算时间很长,也没有多大意义,如果用户输入不正确数字’23’则回
   出现 1-7 所示提示,接着让用户重新输入。
第一章 汉诺塔问题                                         5




               图   1-6                 图   1-7


    当用户输入正确并按回车键后,程序输出所计算出的圆盘移动步数(Steps)和移
  动状态( from * to * ) ,输出结束后,接着输出是否继续的提示信息如图 1-8。当用
  户输入’y’或’Y’后程序继续,用户可再次输入圆盘数进行下一次汉诺塔测试直到用
  户输入’n’或’N’。当用户输入’n’或’N’后,程序结束如下图:




                           图 1-8

1.7. 测试结果
(1) 输入数据的测试.
   程序要求用户输入的数据为 1 至 15 的整型,在测试中分别输入合法的数据和在
 限制范围之外的不合法数据与字符,进行测试,测试结果列入下表中。    (注: 输入
 数据只为圆盘数量 )

                         表 1.1
    输入数据       数据判断                  输出结果
      5            合法                正确结果
      3            合法                正确结果
      16           不合法           无结果,提示输入有误重新输入
      0            不合法           无结果,提示输入有误重新输入
      50           不合法           无结果,提示输入有误重新输入
      d            ———              错误导致死循环
       a           ———              错误导致死循环



(2) 输出结果测试
  1. 测试输出结果,检验程序计算出的输出是否正确:分别取圆盘数为 1,2, 3,
 4 进行测试,并将输出的移动结果进行实物实验检测,具体过程不做列出。
第一章 汉诺塔问题                                          6


  2. 根据正确的时间复杂度分析结果的正确性:因为 Hanoi Tower 程序运算的时间
 复杂度为 O(2^n-1), 记录运行结果的步数,根据数学归纳法可验证程序运行正确。

                           表 1.2
      圆盘数       运行步数          圆盘数       运行步数
      (disks)    (steps)      (disks)    (steps)
        1          1               5      31
        2          3               6      63
        3          7               7      127
        4         15               8      255

				
DOCUMENT INFO
Shared By:
Categories:
Tags:
Stats:
views:6
posted:10/4/2012
language:Unknown
pages:6