今天,在学习C#的时候,遇到了一个很有意思很经典的问题--Hanoi塔(汉诺塔)问题。于是就研究了一下子,现在小小的总结一下。
(1)问题的描述
古代有一个梵塔,塔内有3个座,分别用A、B、C表示。开始时A座有N个盘子,盘子两两大小不等,大的在下,小的在上,盘子编号从上到下分别编号为1到N。B座,C座上面没有盘子。要求将这N个盘子从A移到C上,且在移动的过程中大盘不能压在小盘上。移动过程可以借助B盘中转。
(2)问题的分析
这是一个典型的递归问题,将A转移到C,可以分为下面的这些步骤:
1.如果N=1,那么只需要将盘子从A移到C即可。所以,N=1也是递归终止条件。
2.如果N>1,那么将N-1个盘子从A移到B,利用C做中转。再将第N个盘子从A移到C。
3.接下来,就变成了一个N-1个盘子从B移到C的,A为中转的汉诺塔问题了,就可以直接递归了。
(3)问题的实现
那么,在实现的时候,我用了以前学习的Java和最近正在学习的C#语言来实现它,其实两种语言差不多,在实现这个问题的具体算法上,没有很大的不同。
1.C#版本实现
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace Hanoi { class Program { //总共搬动盘子的次数 static int count = 0; /* *程序入口 */ static void Main(string[] args) { Console.Write("请输入Hanoi塔问题的盘子数目:"); int n = int.Parse(Console.ReadLine()); Hanoi(n,'A','B','C'); Console.WriteLine("移动结束,一共进行了{0}次移动",count); Console.ReadLine(); } /* *输出一个移动步骤的方法 */ public static void PrintMove(char x, char y) { Console.WriteLine("{0}-->{1}", x, y); } /* Hanoi塔递归方法,n是盘子数,one,two,three是3个座 */ public static void Hanoi(int n,char one,char two,char three) { if (n == 1) { ++count; PrintMove(one, three); return; } else { ++count; //把N-1个盘子拿到中转座 Hanoi(n-1,one,three,two); //将第N个盘子移到目标座 PrintMove(one,three); //把中转座上的N-1个盘子移到目标座 Hanoi(n-1,two,one,three); } } } }
?运行结果:
?
1.Java版本实现
import java.util.Scanner; /** * 汉诺塔问题 * xiangpin */ public class Hanoi { //计算搬动盘数目 public static int count=0; /** * 程序入口 * @param args */ public static void main(String[] args) { //从键盘读取数据 System.out.println("请输入汉诺塔问题的盘子数目:"); Scanner scan=new Scanner(System.in); int n=scan.nextInt(); Hanoi(n,'A','B','C'); System.out.println("移动结束,一共移动了"+count+"次"); } /** * 输出移动步骤的方法 */ public static void PrintMove(char x,char y){ System.out.println("从"+x+"移动到"+y); } /** * 汉诺塔的递归方法,n是盘子数,one,two,three是3个座 */ public static void Hanoi(int n ,char A,char B,char C){ //如果N=1,则直接从A搬到C if(n==1){ ++count; PrintMove(A,C); } else{ ++count; //如果n>1,则将n-1个盘子,从A搬到B,C作为中转 Hanoi(n-1,A,C,B); //再将第n个盘子搬到C PrintMove(A,C); //现在问题变成n-1个盘子,从B到C,A为中转的问题了,运用递归 Hanoi(n-1,B,A,C); } } }
?运行结果:
?通过这个例子可以很容易的看出来,利用递归可以很快速且有效的得出结果。另外,我觉得将一种自己较为熟悉的语言和另外一种新学的结合起来学习,是一件很有趣的事情。