最近看数据结构,这篇文章是讲关于 汉诺塔 算法的C#控制台实现的程序。汉诺塔我一般形象的称它为大便,下面是算法这是摘自 [url]http://blog.minidx.com/2008/01/30/457.html[/url]的博客那里的算法写的很清楚了代码是用C++的,我自己用C#改了改了。现在的代码是可以通过的,如果有什么错误还请各位大侠指正。
下面将给出非递归的实现源代码。因为递归的没什么变化。
InBlock.gif public static void Main( string[] args)
InBlock.gif{
InBlock.gif         //非递归解法
InBlock.gif         int n = 5; //这里的n表示圆盘的个数,我写死在程序里了
InBlock.gif        HannoiNotUseRecursion.Pillar[] pillar = new HannoiNotUseRecursion.Pillar[3]; //三根柱子的信息用结构数组存储
InBlock.gif        
InBlock.gif         for ( int i=0; i < pillar.Length;i++)
InBlock.gif        {
InBlock.gif                pillar[i].sElement = new Stack< int>();
InBlock.gif        }
InBlock.gif
InBlock.gif        HannoiNotUseRecursion.Creat(pillar, n); //给结构数组设置初值    
InBlock.gif
InBlock.gif         long max = HannoiNotUseRecursion.Pow(2, n) - 1; //动的次数应等于2^n - 1
InBlock.gif        HannoiNotUseRecursion.Hannoi(pillar, max); //移动汉诺塔的主要函数
InBlock.gif        Console.Read();
InBlock.gif}
我定义了一个名叫HannoiNotUseRecursion的静态类
InBlock.gif public static class HannoiNotUseRecursion
InBlock.gif{
InBlock.gif         /// <summary>
InBlock.gif         /// 计算x^y
InBlock.gif         /// </summary>
InBlock.gif         /// <param name="x"></param>
InBlock.gif         /// <param name="y"></param>
InBlock.gif         /// <returns></returns>
InBlock.gif         public static long Pow( int x, int y)
InBlock.gif        {
InBlock.gif                 long sum = 1;
InBlock.gif                 for ( int i = 0; i < y; i++)
InBlock.gif                {
InBlock.gif                        sum *= x;
InBlock.gif                }
InBlock.gif                 return sum;
InBlock.gif        }
InBlock.gif         /// <summary>
InBlock.gif         /// 给柱子结构数组设置初值
InBlock.gif         /// </summary>
InBlock.gif         /// <param name="pillar">柱子</param>
InBlock.gif         /// <param name="n">圆盘个数</param>
InBlock.gif         public static void Creat(Pillar[] pillar, int n)
InBlock.gif        {
InBlock.gif                pillar[0].Name = 'A';
InBlock.gif                 //把所有的圆盘按从大到小的顺序放在柱子A上
InBlock.gif                 for ( int i = 0; i < n; i++)
InBlock.gif                {
InBlock.gif                        pillar[0].sElement.Push(n - i);
InBlock.gif                }
InBlock.gif
InBlock.gif                 //柱子B,C上开始没有没有圆盘
InBlock.gif                 for ( int i = 0; i < n; i++)
InBlock.gif                {
InBlock.gif                        pillar[1].sElement.Push(0);
InBlock.gif                        pillar[2].sElement.Push(0);
InBlock.gif                }
InBlock.gif
InBlock.gif                 //若n为偶数,按顺时针方向依次摆放 A B C
InBlock.gif                 if (n % 2 == 0)
InBlock.gif                {
InBlock.gif                        pillar[1].Name = 'B';
InBlock.gif                        pillar[2].Name = 'C';
InBlock.gif                }
InBlock.gif                 else     //若n为奇数,按顺时针方向依次摆放 A C B
InBlock.gif                {
InBlock.gif                        pillar[1].Name = 'C';
InBlock.gif                        pillar[2].Name = 'B';
InBlock.gif                }
InBlock.gif        }
InBlock.gif
InBlock.gif         public static void Hannoi(Pillar[] pillar, long max) //移动汉诺塔的主要函数    
InBlock.gif        {
InBlock.gif                 int k = 0; //累计移动的次数
InBlock.gif                 int i = 0;
InBlock.gif                 int ch;
InBlock.gif                 while (k < max)
InBlock.gif                {
InBlock.gif                         //按顺时针方向把圆盘1从现在的柱子移动到下一根柱子
InBlock.gif                        ch = pillar[i % 3].Pop();
InBlock.gif                        pillar[(i + 1) % 3].Push(ch);
InBlock.gif                        Console.WriteLine( string.Format( "{0}: Move disk {1} from {2} to {3}", ++k, ch, pillar[i % 3].Name, pillar[(i + 1) % 3].Name));
InBlock.gif
InBlock.gif                        i++;
InBlock.gif                         //把另外两根柱子上可以移动的圆盘移动到新的柱子上
InBlock.gif                         if (k < max)
InBlock.gif                        {                 //把非空柱子上的圆盘移动到空柱子上,当两根柱子都为空时,移动较小的圆盘
InBlock.gif                                 if (pillar[(i + 1) % 3].Top() == 0 ||
InBlock.gif                                        pillar[(i - 1) % 3].Top() > 0 &&
InBlock.gif                                        pillar[(i + 1) % 3].Top() > pillar[(i - 1) % 3].Top())
InBlock.gif                                {
InBlock.gif                                        ch = pillar[(i - 1) % 3].Pop();
InBlock.gif                                        pillar[(i + 1) % 3].Push(ch);
InBlock.gif                                        Console.WriteLine( string.Format( "{0}: Move disk {1} from {2} to {3}", ++k, ch, pillar[(i - 1) % 3].Name, pillar[(i + 1) % 3].Name));
InBlock.gif                                }
InBlock.gif                                 else
InBlock.gif                                {
InBlock.gif                                        ch = pillar[(i + 1) % 3].Pop();
InBlock.gif                                        pillar[(i - 1) % 3].Push(ch);
InBlock.gif                                        Console.WriteLine( string.Format( "{0}: Move disk {1} from {2} to {3}", ++k, ch, pillar[(i + 1) % 3].Name, pillar[(i - 1) % 3].Name));
InBlock.gif                                }
InBlock.gif                        }
InBlock.gif                }
InBlock.gif
InBlock.gif        }
InBlock.gif
InBlock.gif         /// <summary>
InBlock.gif         /// 用来表示每根柱子的信息
InBlock.gif         /// </summary>
InBlock.gif         public struct Pillar
InBlock.gif        {
InBlock.gif                 //存储每根柱子套的上的圆盘情况
InBlock.gif                 public Stack< int> sElement;
InBlock.gif                
InBlock.gif                 //柱子的名字,可以是A,B,C中的一个
InBlock.gif                 public char Name;
InBlock.gif                 /// <summary>
InBlock.gif                 /// 出栈
InBlock.gif                 /// 把盘子从柱子中挪走
InBlock.gif                 /// </summary>
InBlock.gif                 /// <returns></returns>
InBlock.gif                 public int Pop()
InBlock.gif                {
InBlock.gif                         return sElement.Pop();    
InBlock.gif                }
InBlock.gif                 /// <summary>
InBlock.gif                 /// 入栈
InBlock.gif                 /// 把盘子放入柱子中
InBlock.gif                 /// </summary>
InBlock.gif                 /// <param name="x"></param>
InBlock.gif                 public void Push( int x)
InBlock.gif                {
InBlock.gif                        sElement.Push(x);
InBlock.gif                }
InBlock.gif                 /// <summary>
InBlock.gif                 /// 取栈顶元素
InBlock.gif                 /// </summary>
InBlock.gif                 /// <returns></returns>
InBlock.gif                 public int Top()
InBlock.gif                {
InBlock.gif                         if (sElement.Count == 0)
InBlock.gif                        {
InBlock.gif                                 return 0;
InBlock.gif                        }
InBlock.gif                         else
InBlock.gif                        {
InBlock.gif                                 return sElement.Peek();
InBlock.gif                        }
InBlock.gif                }
InBlock.gif        }
InBlock.gif}
这里在叫Pillar(柱子)的结构体里有一个类型为Stack (栈)的属性用于存储每个柱子上的圆盘,Name属性表示柱子的名称。