解决河内难题塔的递归方法

时间:2016-02-15 04:28:42

标签: java algorithm recursion towers-of-hanoi

我试图找出河内的塔楼#34;问题,它通过一个辅助堆栈将从最小到最大的磁盘堆栈从一个起始堆栈移动到一个目标堆栈,而不需要在较小的磁盘上放置一个较大的磁盘。

我得到了算法:

If numberDisks ==  1:
   Display “Move the top disk from  S to D”.
Else
  Move(numberDisks -1, ‘S’, ‘A’, ‘D’);
  Move(1, ‘S’, ‘D’, ‘A’);
  Move(numberDisks -1, ‘A’, ‘D’, ‘S’);

然而,这似乎与大多数其他examples不同,它们似乎在不使用Move(1,'S','D','A')的情况下工作;在递归函数中。

正如我的代码所代表的那样,我似乎重复每一步的基本情况,并且我不确定如何构造我的print语句以提供应该如下的正确输出:

Move disk 1 from S to D
Move disk 2 from S to A
Move disk 1 from D to A
Move disk 3 from S to D
Move disk 1 from A to S
Move disk 2 from A to D
Move disk 1 from S to D

尝试移动3个磁盘时。

// Recursively solve Towers of Hanoi puzzle

public static void main(String[] args) {
    if (handleArguments(args)) {
        System.out.println("numDisks is ok");
        int numDisks = Integer.parseInt(args[0]);

        Move(numDisks,'s', 'a', 'd' );
    }
}

// recursive case
public static void Move(int disks, char start, char aux, char destination) {

    // base case
    if (disks == 1) {
        System.out.println("Move disk 1 from S to D");

        // if number of disks is 2 or greater
    } else if(disks > 1) {
        Move(disks - 1, start, aux, destination);
        System.out.println("move disk " + disks + " from " + start + " to " + destination);
        Move(1, start, destination, aux);
        Move(disks - 1, aux, destination, start);
    }
}

1 个答案:

答案 0 :(得分:1)

第一件事:了解移动n张光盘的算法(从S到D,用A)

  1. 如果只有一张光盘要移动,只需移动它然后停止*。
  2. 使用D。
  3. 将n - 1张光盘从S移动到A.
  4. 将第n张光盘从S移至D
  5. 使用S
  6. 将n - 1张光盘从A移动到D.

    *同样:如果有0张光盘,请停止。 (有些人认为这是优越的终止条件,因为在你的代码中,当有一个特殊情况时,它会阻止print语句,它将由你用第3步所覆盖的print语句自然处理。当,例如,您决定更改此方法以返回步骤列表而不是打印它,此更改只需在一个位置应用)

    你提到那个"我似乎重复每一步的基本情况。"如果你查看你的代码,并与我上面的陈述进行比较。你会看到我在我的第3步和第4步之间拨打Move(1, start, destination, aux);。这就是你重复基本情况的原因,因为你明确地打电话,重复你的基本情况,但它没有任何意义。

    我可以看到另一个主要问题: System.out.println("Move disk 1 from S to D");将始终打印' S'和' D'按此顺序,当您经常需要指定不同的移动时,请确保使用此语句的参数。

    我不认为还有别的东西,但试试看。

    回复你在帖子开头给出的例子。它产生的输出与您的版本略有不同。

    您指定(或尝试)每一步应移动哪个尺寸的光盘,该示例仅指定从哪个堆栈移动光盘,无论其大小如何。

    在中间使用1作为参数的递归调用将打印移动指令以移动堆栈中的最终光盘(我的步骤3)。