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

算法理解:

理解1:

宏观上我们可以这样理解:要将A上的n个盘子按照要求移动到C上,我们可以想到:将上边的 n-1 的盘子移动到B上,将上边的 n-2 个盘子移动到A,再将B上盘子移动到C上,然后将A上所有的盘子移动到C上,B做为踏板,这是比较简单的理解,但是对于算法实现的过程,还是没有弄透彻。

理解2:

我们知道当盘子数为n时,移动的次数应该为 2^n-1;这个有公式  H(n) = 2H(n-1) +1 得来,理解为:上边的n-1个盘子先翻转到B上,将最大的盘子移动到C上,花费1步,然后将B上的盘子翻转到C上,花费2H(n-1)步。

后来美国的一位学者发现一种出人意料的简单的算法,只要轮流两步操作既可以实现:首先,把三张桌子按顺序首尾相接的排列,形成一个环,然后对A上的盘子开始移动,顺时针摆放成 A B C的顺序:

若n为奇数,圆盘的移动顺序是 A->C->B->A->C->B->A......... 即 间隔两个步长移动  。此处的n代表盘子位的层数,比如说 3 层汉诺塔就是从下往上数第1、3 个盘子移动的顺序。

若n为偶数,圆盘移动的顺序为A->B->C->A->B->C->A..........即 间隔一个步长移动。对n的解释同上 第二个盘子移动 A->B->C。


下边是两种类似的解题思路,唯一不同的是,三个位置变量的顺序有差异,暂时由于学业的原因,没有进行完善,还请担待,后期会继续完善。

一、

#!/bin/bashcount=0n_1()
#步数的统计及盘子的移动都是通过第一个函数调用来完成,
{                let count++   
                                 echo "第${count}步:将${2}号圆盘从${1}移动到${3}"}n_2()
{                if [ $1 -eq 1 ];then
                     #如果位置变量1等于1的话,判断成立,进行调用第一个函数
                     n_1 $2 1 $4
                else            
                     #不成立进行此步骤,此循环调用函数调用于判断第一个盘子将移动到那个柱子上,循环过程下边有说明。
                     n_2 $[$1-1] $2 $4 $3
                      #此函数调用,用于辅助上下函数调用进行输出。
                     n_1 $2 $1 $4
                     #此步骤进行后续循环调用,上一个n_2负责把盘子从第一个柱子移走到第二个柱子上,
                     #这个n_2负责把第二个柱子上的盘子移动到第三个柱子上。
                     #中间的n_1负责最终要的一部将最大的盘子从第一个柱子移动到最后一个柱子上。
                     n_2 $[$1-1] $3 $2 $4
                fi
                }
                read -p "please input the number: " num
                n_2 $num X Y Z

     num=3
     n_2 3 X Y Z
            n_2 2 X Z Y
                n_2 1 X Y Z
                    n_1 X 1 Z
                        输出:第1步:将1由X移到Z
                n_1 X 2 Y
                    输出:第2步:将2由X移到Y
                n_2 1 Z X Y
                    n_1 Z 1 Y
                        输出:第3步:将1由Z移到Y
            n_1 X 3 Z
                输出:第4步:将3由X移到Z
            n_2 2 Y X Z
                n_2 1 Y Z X
                    n_1 Y 1 X
                        输出:第5步:将1由Y移动X

                n_1 Y 2 Z
                    输出:第6步:将2由Y移到Z

                n_2 1 X Y Z
                    n_1 X 1 Z
                        输出:第7步:将1由X移到Z

二、下边方式还有待完善,能出结果,但是步骤详解没有做,仅做参考 。

#!/bin/bash
sun=0
funa() {
    let asd--
    let sun++
    echo "步数 : $sun   盘子 :  $1   移动方向: $2   ---->  $3 "  
}
funb() { 
    if [ $1  -eq  1 ];then  #当
        funa $1   $2   $4
        #     N   A     C
    else
        funb "$[$1-1]" $2  $4  $3
        if [   $? -eq  0 ];then
        echo "==================================================================$asd ---fun1"
        fi    
#1       N-1(4)    A    C   B  ------>  A(A)   B(C)    C(b)   
#3 B  a  c    
#    N-2(3)    A   B    C  ------->  A   B    C       Ab   Bc   Ca
#     2        a   c   b    ------->  A    Bc        Cb
#    1       a    c   b  ------    a   b   c
        funa $1  $2  $4
        if [ $? -eq 0  ];then
        echo "-=================================================================$asd ----fun2" 
        fi
        #1    N    A   C
        # N-1(4)  A   B
        # N-1(4)  B   C
        #N-2 (3)     \
#               b--a
#               c--b         
        funb "$[$1-1]" $3  $2  $4
        if [ $?  -eq  0  ];then
        echo "===================================================================$asd ----fun3"
        fi
#1   N-1 4      B   A    C   ---->  A(B)  B(A)  C(C )   
#3                       a  c   b    
#2   N-1 3      a   B    C      ---->   Ac    Ba      Cb
#      2       B   a  C             
#        1
    fi
}
read -p "shuru panshu : " asd
funb $asd A B C