Hanoi塔(汉诺塔)问题如下图:
设X Y Z为三个塔座,开始时再塔座上有n个圆盘,他们自上而下由小到大的叠放着,编号依次为1,2,...,n,现在要求将塔座X上的这一叠圆盘移到塔座Z上,并按同样顺序叠放,在移动时要遵循以下规则:
(1)每次只能移动一个圆盘;
(2)任何时刻都不允许将较大的圆盘放在较小的圆盘之上;
(3)在满足(1)(2)两个条件的情况下,可以将圆盘放在任意塔座上。
这个问题有两种解决方法:一个是利用递归的方法,易于理解,但空间和时间复杂度较高;另一种还是比较简单的方法,但理解起来较困难些。
1.先说下递归的方法:要将1到n个圆盘放在Z上,可以分三步走,先将1到n-1个圆盘按照规则放在过渡塔座Y上,再把圆盘n放到Z的底部,最后再把Y上的1到n-1个圆盘再按规则放到Z中圆盘n上。而对于1到n-1圆盘的移动又可以同理递归到第1到n-2个圆盘的操作上,如此类推:
很自然的可以得到如下程序:
/* *@param n 移动第1到n个圆盘 *@param src 从塔座src上移动 *@param des 移动到des塔座上 *@param t 以t塔座为过渡 */ public void hanoi(int n, int src, int des, int t){ if(n > 1){ hanoi(n - 1, src, t, des); move(n, src, des); //将第n个圆盘从X移动到Z hanoi(n - 1, t, des, src); }else{ move(n, src, des); } }
2.另一种非递归方法:假设塔座X,Y,Z排成一个三角形:Z -> Y -> X -> Z。其中X是源塔座,Z是目的塔座。构成一个循环的三角形。在移动圆盘的过程中,若是奇数词移动,则将最小的圆盘移动到其所在塔座的下一个塔座上;若是偶数次移动,则保持最小的圆盘不懂,而其他两个塔座之间,将较小的圆盘移动到另一塔座上。