汉诺塔问题基于java的递归代码详解

  • 简单带过汉诺塔问题
  • 问题求解思路
  • 汉诺塔代码递归实现(Java)
  • 代码混淆点详解


简单带过汉诺塔问题

汉诺塔简介:汉诺塔(Tower of Hanoi),是一个源于印度古老传说的益智玩具。大梵天创造世界的时候做了三根金刚石柱子,在一根柱子上从下往上按照大小顺序摞着64片黄金圆盘。大梵天命令婆罗门把圆盘从下面开始按大小顺序重新摆放在另一根柱子上。并且规定,在小圆盘上不能放大圆盘,在三根柱子之间一次只能移动一个圆盘。(在我们的讲解中仅以三个圆盘举例)

java用递归实现汉诺塔 java 汉诺塔 如何递归的_java

问题求解思路

对于汉诺塔问题的求解思路分为两个阶段,首先我们必须将汉诺塔中的所有圆盘分为两个部分,分别为 【1】Tower1中最下边的那个圆盘 【2】除此之外的所有圆盘。若设总圆盘数为n,则【1】的值为1,【2】的值为n-1。确定这件事之后我们就可以确定求解的两个阶段:
1>将Tower1上【2】中的圆盘全都移到Tower2中,这个过程可以借助Tower3来完成。
在所有【2】中圆盘全都转移之后,将【1】中唯一的大圆盘移入Tower3。
2>将Tower2上所有的【2】中圆盘按照游戏规则移入Tower3,可以借助Tower1来完成。
在确定这些事之后,我们便可以使用递归来完成代码。

汉诺塔代码递归实现(Java)

以三个圆盘为例:

public class HanoiTower {
    public static void main(String[] args){
        hh hhanoi = new hh();
        hhanoi.Hanoi(3,"Tower1","Tower2","Tower3");
    }
}

class hh {
    public void Hanoi(Integer n, String a, String b, String c) {
        if (n == 1) {
            System.out.println(a + "->" + c);
        } else {
            Hanoi(n - 1, a, c, b);
            System.out.println(a + "->" + c);
            Hanoi(n - 1, b, a, c);
        }
    }
}

以下是运行结果:

java用递归实现汉诺塔 java 汉诺塔 如何递归的_java用递归实现汉诺塔_02


此文章我主要想要讲解的是这个代码的运行过程,写这篇文章的初心也是最初被里边的参数绕的有点晕,弄清楚之后大为无语。

代码混淆点详解

首先我先入为主的认为大家想必已经对递归有所了解
这个代码如果令你云里雾里绕不明白,我想关键问题一定是在每次递归的汉诺塔柱子排序上。
其实很好理解,你可以将代码中的参数a,b,c看做成数字排序1,2,3。
如第一次执行时我们函数中的参数为{3,a,b,c},因为不满足if语句的条件,所以执行了else中的语句 Hanoi(n - 1, a, c, b);此时参数就变成了{2,a,c,b}。
但是应当注意,此语句中的a,c,b并非是每次都按a,c,b排列,这里a,c,b只是一种排序方式,即改变了上一个参数中的顺序,将第3个位置和第2个位置调换。 如当参数{2,a,c,b}进入下一次递归时,其参数并非是{1,a,c,b},而是{1,a,b,c}。下一行输出语句后的函数亦是同理,可以看做是将目前的参数的顺序看为{1,2,3},而{b,a,c}的意思是将其按照{2,1,3}排序。

之后我们可以做几次尝试,将参数{3,“Tower1”,“Tower2”,“Tower3”}传给方法Hanoi()。
不满足if语句所以进入第一次递归,参数变为{2,“Tower1”,“Tower3”,“Tower2”}。
因为不满足if语句,故在此进入递归,参数变为{1,“Tower1”,“Tower2”,“Tower3”}。
此时满足if语句,则执行输出(a + “->” + c),此时的a,即上文所讲的第一个参数,c为最后一个参数,故应输出Tower1->Tower3。

此后的代码同理。