递归中的汉诺塔问题(Java 实现)
需要动手玩一玩才能更好更直观的理解这个问题:http://www.7k7k.com/swf/37623.htm
记得在大一的时候 C语言讲到递归的时候,这个汉诺塔就折磨了我很久,可是依然没怎么搞明白。现在学到Java了,下决心给他搞定一下。弄明白了之后其实也并不是那么难。其中心思想,就是递归的中心思想。只需要把复杂问题的实现抽象成几部分问题的实现。至于每一步的问题如何实现,我们程序员没必要过于关心,只需要利用递归,继续调用递归的中心思想,将其拆分为相同的几部分问题的实现。 但是这样一直递归递归递归 总有结束的时候,这就是递归出口。
例如汉诺塔问题的递归出口就是,如果只需要移动的是一个盘子 则直接move()然后程序结束。
来一段官方一点的话,再去品一品什么是递归。
递归:是指在定义自身的同时,又出现了对自身的引用。如果一个算法直接或间接地调用自己,则称这个算法是一个递归算法。
任何一个有意义的递归算法总是由两部分组成:递归调用和终止条件。
百度百科上递归是这么解释的:递归算法(英语:recursion algorithm)在计算机科学中是指一种通过重复将问题分解为同类的子问题而解决问题的方法。
解决思路!!!!
hanio(int n,char x, char y, char z )函数中参数的意义:hanio这个函数的作用就是将n个盘子 从 x塔 经过y辅助塔, 最终到达目标z塔。
为了贴合我的代码 , 我们将tower1 定义为x塔 tower2定义为y塔 tower3定义为z塔
如何将x塔中的n个盘子大小顺序不变放到z塔呢?----------> hanio(n,x,y,z);
我们抽象为3步
第一步 将x塔中n-1个盘子 通过辅助塔 z 先放到y 塔 -------> hanio(n-1,x,z,y)
第二步 将x塔中第n个盘子移动到 z 塔 --------->move(n,x,z)
第三步 再将y塔上的 n-1个盘子 通过辅助塔x 全部移动到 z塔上面,就完成了。 --------> hanio(n-1,y,x,z)
仔细的思考一下,我们好像还没有设置递归的出口。于是在每次大幅度移动(调用hanio 函数)时 先判断 塔中盘子是否为1个,如果只有一个则直接移动到目的地( move(x,n,z) 无需借助辅助塔 直接将第n个盘子从初始塔 移动到目标塔。)
代码如下:
package ChapterFive.Part2;
/**
* n阶汉诺塔的移动步骤
*
* @author meng
*
*/
public class HanoiDemo {
private static int count = 0;
public static void main(String[] args) {
hanio(3,'x','y','z');
System.out.println(" 总共移动了 " + count + " 次" );
}
/**
* 移动
* @param n 共需要移动的盘子
* @param x 从起始位置
* @param y 借助辅助塔
* @param z 移动到终止位置
*/
public static void hanio(int n, char x, char y, char z) {
count++;
if(n==1) {
move(x,n,z);
}else {
hanio(n-1,x,z,y);
move(x,n,z);
hanio(n-1,y,x,z);
}
}
/**
* 打印移动
* @param x 从起使位置
* @param n 移动第几个盘子
* @param y 要移动到的最终位置
*/
private static void move(char x, int n, char y) {
// TODO Auto-generated method stub
System.out.println(" Move " + n + " from " + x + " to " + y);
}
}
输出结果
Move 1 from x to z
Move 2 from x to y
Move 1 from z to y
Move 3 from x to z
Move 1 from y to x
Move 2 from y to z
Move 1 from x to z
总共移动了 7 次