尝试使用我自己的程序了解河内算法

时间:2016-06-19 19:43:10

标签: java algorithm recursion tree

我有以下河内塔的工作程序,我们将从A - B塔移动磁盘,C是额外的塔。我定义了函数的初始状态如下:moveDisks(n, 'A', 'B', 'C');

每次我使用以下算法进行移动时都会打印:

public static void moveDisks(
        int n,
        char fromTower,
        char toTower,
        char auxTower)
    {
        if (n == 1) // Stopping condition
            System.out.println(
                "Move disk " + n + " from " + fromTower + " to " + toTower);
        else
        {
            moveDisks(n - 1, fromTower, auxTower, toTower);
            System.out.println(
                "Move disk " + n + " from " + fromTower + " to " + toTower);
            moveDisks(n - 1, auxTower, toTower, fromTower);
        }
    }
}

从我的程序中的递归调用可以看出,我有三个可能的调用:

    A--B--C //fromTower, toTower,auxTower
    A--C--B //fromTower, auxTower, toTower
    C--B--A //auxTower, toTower, fromTower

但是,我正在为3个磁盘获取以下打印输出:

The moves are:
Move disk 1 from A to B
Move disk 2 from A to C
Move disk 1 from B to C
Move disk 3 from A to B
Move disk 1 from C to A
Move disk 2 from C to B
Move disk 1 from A to B

我知道我的程序是正确的,但我并没有真正了解它是如何进行B--CC--A调用的,因为我从未做过这样的函数/方法。如果你能证明这个递归的方式,我将不胜感激。方法使用我的A--B--CfromTower, toTower,auxTower模型在三个磁盘方面工作。

2 个答案:

答案 0 :(得分:3)

我终于弄清楚了这一点。我可以看到它在二进制树结构中令人惊讶,在递归中首先调用最左边的子节点(在这种情况下,子节点是一个print语句)。

我理解的错误是,我假设所有递归调用awk '{print gsub (srch,srch)}' srch="n" A--B--C,尽管from-to-aux变量一直在变化。所以当我开始时from-to-auxn=3,我接到以下调用:A= from,B=to, C= auxmoveDisks(2, 'A', 'C', 'B')。现在,每个递归调用将独立启动自己的调用,但现在第一个调用{{ 1}}和第二个moveDisks(2, 'C', 'B', 'A')。因此,对于第一个我得到A=from, C=to, and B=auxC=from, B=to and A=aux来电,第二个得到moveDisks(1,'A','B','C')moveDisks(1,'B','C','A')来电.Recursion继续到达停止点。

enter image description here

注意:这真是太神奇了!我正在学习递归,但最终也学习了二叉树!

答案 1 :(得分:0)

您正在考虑仅从初始调用的角度调用moveDisks

moveDisks(.., 'A', 'B', 'C')

将致电

moveDisks(.., 'A', 'C', 'B')
moveDisks(.., 'C', 'B', 'A')

但递归将继续进行这些调用,因此下一轮调用将是

moveDisks(.., 'A', 'B', 'C')
moveDisks(.., 'B', 'C', 'A')  --> moving B to C

moveDisks(.., 'C', 'A', 'B')
moveDisks(.., 'A', 'B', 'C')

...