目录
例题简介
汉诺塔问题是一个经典的问题。汉诺塔(Tower of Hanoi),又称河内塔,源于印度一个古老传说。大梵天创造世界的时候做了三根金刚石柱子,在一根柱子上从下往上按照大小顺序摞着64片黄金圆盘。大梵天命令婆罗门把圆盘从下面开始按大小顺序重新摆放在另一根柱子上。并且规定,任何时候,在小圆盘上都不能放大圆盘,且在三根柱子之间一次只能移动一个圆盘。问应该如何操作?
如果不太明白 可以去这个网址玩玩游戏
http://www.4399.com/flash/109504_1.htm
解题思路
1. 先引用实例分析
引入三个名词:原始柱:即提供盘子的柱子;
目的柱:即要接收盘子的柱子;
辅助柱:即需要帮助完成该过程的柱子。
假设只有1个盘,则需要做的就是直接 A->C 即将原始柱移入目标柱
再者,假设2个盘,则操作是 A->B, A->C,B->C 这种情况下,我们要想把A中的所有盘移到C盘,需要借助B盘,我们称B盘为辅助柱。
继续,假设3个盘,这时候我们分三部步看。第一步:将A盘的前两个盘移给B盘,这个方法就跟我们上一个是一样了,A为原始柱,B为目的柱,C为辅助柱。第二步:将A盘的最后一个盘移给C盘。第三步:将B盘的两个盘移给C盘,这时候,我们以A为辅助柱,B为原始柱,C为目的柱。
2.带N分析
即我们假设A中盘的个数为N
那么此刻,即最初的时候,我们以A为原始柱,B为辅助柱,C为目的柱
好 那么这里,有没有想问 我们要辅助柱是用来干嘛呢??
我们将A中的N个盘全部移到C中,是不是要先将A中最大的盘移给C,所以,我们希望辅助盘B能够先承载(N-1)个盘
通过这个讲解,你是不是已经发现循环了。
接上面的步骤,我们要把A中的(N-1)个盘移给B,此时我们需要C作为辅助盘。你再试着推推,不就是一直循环了吗。
3.递归方法
递归有两个很重要的基本概念,即,基本情形和递归情形。
基本情形: 简单来说,就是我们这个递归,这个很大循环的一个出口。
递归情形:就是我们重复调用该递归函数的情况。
根据上面的分析,我们有个循环体,就是原始柱上的所有盘移给目的柱。
我们这一题的出口是,当原始柱只剩一个盘的时候,我们要做最后一步,将原始柱上的盘子移给目的柱,然后退出就好了。
要是原始柱不只剩一个盘,那么我们需要做三步,即两次调用:
第一步:将原始柱上的(N-1)个盘移给辅助柱。
第二步:将原始柱上的第N个盘(即最后一个)移给目的盘,这种情况也就是我们上面所说的基本情形,也就是出口了。
第三步:将辅助柱上的(N-1)个盘移给目的盘。
代码
/*
* 递归算法 典型例题
* 汉诺塔
* 通过对题目的掌握,可知 每个塔可作为三种角色 即 目的塔、辅助塔、原塔
*
*/
public class TowersOfHanoi {
static int time = 0;
public static void function(int n, char source, char assistant, char target) {
//若只剩下一个,直接移给 目的塔 就完成了
//此为该递归的出口 即基本情形
if(n == 1) {
time++;
System.out.println("Time:\t" + time +"\t" +"Move " + source + " to " + target);
return;
}
//此为递归情形
else {
//若不是剩下最后一个,我们要想将前面的(n-1)移给 辅助塔
function(n-1, source, target, assistant);//
time++;
System.out.println("Time:\t" + time +"\t" +"Move " + source + " to " + target);
//然后将辅助(n-1)个移给 目标塔
function(n-1, assistant, source, target);
}
}
public static void main(String[] args) {
function(8, 'A', 'B', 'C');
}
}