汉诺塔问题实现比较简单,几个递归语句和输出语句就可以实现,但是一直没能明白是怎能具体实现的,云里雾里的感觉,今天仔细想了一下,梳理一些。
1.Java完整代码:
package DataStructure.CommonAlgorithms.DivideAndConquer;
/**
* @author : DR
* @version : 1.0
* @date : 2022/3/14/12:54
* @Problem description:Hanoi
* @Solution:Recursion
*/
public class DivideAndConquerDemo {
public static void main(String[] args) {
hanoi(2, 'A', 'B', 'C');
}
public static void hanoi(int number, char a, char b, char c){
if (number == 1){
System.out.println(a + "-->" + c);
}else{
hanoi(number - 1, a, c, b);
System.out.println(a + "-->" + c);
hanoi(number - 1, b, a, c);
}
}
}
1.1输出结果:
1.2核心代码:
if (number == 1){
System.out.println(a + "-->" + c);
}else{
hanoi(number - 1, a, c, b);
System.out.println(a + "-->" + c);
hanoi(number - 1, b, a, c);
}
2.递归解释:
以两个盘为例子,学的时候都知道,分治的思想就是把圆盘分为两部分【最后一个圆盘, 最后一个圆盘以上的所有圆盘】。利用递归可以分为三步:
①先把上面的圆盘从A柱都放在B柱上
hanoi(number - 1, a, c, b);
②把最后一个圆盘从A柱移动到C柱
System.out.println(a + "-->" + c);
③将之前移动到的B柱上的圆盘移动到C柱上去
hanoi(number - 1, b, a, c);
解释:
–>进入程序后,number = 2,直接进入else语句中的hanoi(number - 1, a, c, b);
,要注意的是,当进入此递归后,他的形参就发生了变化,这也是容易造成混淆的主要原因。其实可以改写成hanoi(1, a, c, b);
,此时将会继续执行System.out.println(a + "-->" + c);
语句。对照形参列表可以知道,此时输出语句中的(a + "-->" + c
其实是(a + "-->" + b
.所以会输出结果中的第一句话A-->B
–>执行完上一步之后就会跳出当次的递归也就是下图中的语句1,然后进入语句2,需要注意的是,跳出语句1后,执行语句2时其形参列表顺序是【number, a, b, c】即又恢复到原来的形参顺序形式。此时输出(a + "-->" + c
,对应输出结果的**A-->C
**
–>最后执行语句3,进入次递归后形参也发生相应的变化,相当于执行了
所以此时的System.out.println(a + "-->" + c)
会输出**B-->C
**,此时遍历完毕退出。
注:
①目前只是解释了两个圆盘的过程,若是有多个圆盘,前面的步骤也和此过程类似。
②视频课中老师提到hanoi(number - 1, a, b, c);
,把其解释为把number - 1
个元素从a柱利用b柱的辅助将其移动到c柱。其实我觉得b(也就是中间的那个形参)是没啥用的,用不到,只是为了避免语法错误。每次递归形参列表发生变化的时候也只是首位两参数发生变化。
最后:
阶段性总结,错误请指出,务喷