汉诺塔(Tower of Hanoi),又称河内塔,是一个源于印度古老传说的益智玩具。大梵天创造世界的时候做了三根金刚石柱子,在一根柱子上从下往上按照大小顺序摞着64片黄金圆盘。大梵天命令婆罗门把圆盘从下面开始按大小顺序重新摆放在另一根柱子上。并且规定,在小圆盘上不能放大圆盘,在三根柱子之间一次只能移动一个圆盘。
设有三根柱子,分别命名为A,B和C,有n个圆盘,圆盘开始时都在A上,目标为将所有的圆盘从A搬到C上,为了找规律方便,我们先从只有一个圆盘开始。
当n=1时,只需要把A上的圆盘直接从A搬到C上即可,操作为:
第1个圆盘从A搬到C
当n=2时,则需要借助B,才可以实现目标,具体操作为:
第1个盘子从A搬到B
第2个盘子从A搬到C
第1个盘子从B搬到C
当n=3时,同样需要借助B,且为了不让大圆盘压在小圆盘上,其中有些操作也需要借助A,才可以实现目标,具体操作为:
第1个盘子从A搬到C
第2个盘子从A搬到B
第1个盘子从C搬到B
第3个盘子从A搬到C
第1个盘子从B搬到A
第2个盘子从B搬到C
第1个盘子从A搬到C
此时这些结果已经足够我们来总结规律了。在搬运的整个过程中,最关键的是将第n个圆盘从A搬到C,因为这是n为任何值时,都需要执行的操作,且只要将最大的圆盘搬移完后,其他的圆盘则会简单很多。借此,可将所有的操作大致总结为:
将n - 1个圆盘从A搬到B(为了给第n个圆盘留出C的空间)
将第n个圆盘直接从A搬到C
将n - 1个圆盘从B搬到C
至此,则完成了n个圆盘的搬移。
巧妙的是,从以上规律可以看出解决这个问题的关键是将大事化小,这正好符合递归的思想,则可以考虑用递归函数来求解,并将函数编写为:
public static void hanoi(int n, char A, char B, char C)
此函数为将前n个圆盘从A借助B搬到C,其中A代表需要搬移的柱子,B代表在搬移途中需要借助的柱子,C代表搬移到的柱子,在调用时,只需将三个柱子按照目的来对应参数即可,不需要具体去思A,B,C的值。
在确认了目标和途径后,便可以着手来编写代码块了。首先,需要先确定递归的出口,即当n = 1时,不再执行递归,此时的操作为:将d第1个圆盘从A搬到C上。然后可以来思考递归函数的主体了。但在思考前,需要明确一个关键点,即递归函数在编写时,不需要考虑递归函数的具体执行过程,只需要明确执行后的结果,可以理解为在调用函数时,此函数自动将我们的需求完成。第一步为将第将n - 1个圆盘从A借助C搬到B,第二步为将第n个圆盘从A搬到C,第三步为再将n - 1个圆盘从B搬到C。
具体函数为:
public static void hanoi(int n, char A, char B, char C){
if(n == 1){
//递归出口 System.out.println("第" + n + "个盘子从" + A + "搬到" + C); return; } hanoi(n - 1, A, C, B); //将前n - 1个圆盘从A借助C搬到B System.out.println("第" + n + "个盘子从" + A + "搬到" + C); //将第n个圆盘直接从A搬到C上 hanoi(n - 1, B, A, C); //将前n - 1个圆盘从B借助A搬到C }
main函数为:
public static void main(String[] args) {
char A = 'A'; char B = 'B'; char C = 'C'; Scanner sc = new Scanner(System.in); System.out.println("输入层数:"); int n = sc.nextInt(); hanoi(n, A, B, C); sc.close(); }
结果为: