Chinaunix首页 | 论坛 | 博客
  • 博客访问: 494250
  • 博文数量: 77
  • 博客积分: 1047
  • 博客等级: 少尉
  • 技术积分: 898
  • 用 户 组: 普通用户
  • 注册时间: 2011-08-25 17:16
文章分类

全部博文(77)

文章存档

2016年(2)

2013年(2)

2012年(33)

2011年(40)

分类: C/C++

2011-10-19 19:00:19

汉诺塔算法c++源代码(递归与非递归)

算法介绍:
其实算法非常简单,当盘子的个数为n时,移动的次数应等于2^n - 1(有兴趣的可以自己证明试试看)。后来一位美国学者发现一种出人意料的简单方法,只要轮流进行两步操作就可以了。首先把三根柱子按顺序排成品字型,把所有的圆盘按从大到小的顺序放在柱子A上,根据圆盘的数量确定柱子的排放顺序:若n为偶数,按顺时针方向依次摆放 A B C
n为奇数,按顺时针方向依次摆放 A C B
1)按顺时针方向把圆盘1从现在的柱子移动到下一根柱子,即当n为偶数时,若圆盘1在柱子A,则把它移动到B;若圆盘1在柱子B,则把它移动到C;若圆盘1在柱子C,则把它移动到A
2)接着,把另外两根柱子上可以移动的圆盘移动到新的柱子上。即把非空柱子上的圆盘移动到空柱子上,当两根柱子都非空时,移动较小的圆盘。这一步没有明确规定移动哪个圆盘,你可能以为会有多种可能性,其实不然,可实施的行动是唯一的。
3)反复进行(1)(2)操作,最后就能按规定完成汉诺塔的移动。

所以结果非常简单,就是按照移动规则向一个方向移动金片:
3阶汉诺塔的移动:A→C,A→B,C→B,A→C,B→A,B→C,A→C

汉诺塔问题也是程序设计中的经典递归问题,下面我们将给出递归和非递归的不同实现源代码。

汉诺塔算法的递归实现C++源代码

点击(此处)折叠或打开

  1. #include <fstream>
  2. #include <iostream>

  3. using namespace std;

  4. ofstream fout( "out.txt" );

  5. void Move(int n,char x,char y)

  6. {
  7.     fout<<"把"<<n<<"号从"<<x<<"挪动到"<<y<<endl;
  8. }

  9. void Hannoi(int n,char a,char b,char c)
  10. {
  11.     if(n==1)
  12.         Move(1,a,c);
  13.     else
  14.     {
  15.         Hannoi(n-1,a,c,b);
  16.         Move(n,a,c);
  17.         Hannoi(n-1,b,a,c);
  18.     }
  19. }

  20. int main()
  21. {
  22.     fout<<"以下是7层汉诺塔的解法:"<<endl;
  23.     Hannoi(7,'a','b','c');
  24.     fout.close();
  25.     cout<<"输出完毕!"<<endl;
  26.     return 0;
  27. }

 

汉诺塔算法的递归实现C源代码:

点击(此处)折叠或打开

  1. #include<stdio.h>

  2. void hanoi(int n,char A,char B,char C)
  3. {
  4.     if(n==1)
  5.     {
  6.           printf("Move disk %d from %c to %c\n",n,A,C);
  7.     }
  8.     else
  9.     {
  10.           hanoi(n-1,A,C,B);
  11.           printf("Move disk %d from %c to %c\n",n,A,C);
  12.           hanoi(n-1,B,A,C);
  13.     }
  14. }

  15. void main()
  16. {
  17.     int n;
  18.     printf("请输入数字n以解决n阶汉诺塔问题:\n");
  19.     scanf("%d",&n);
  20.     hanoi(n,'A','B','C');
  21. }


汉诺塔算法的非递归实现C++源代码

点击(此处)折叠或打开

  1. #include <iostream>

  2. using namespace std;

  3. //圆盘的个数最多为64
  4. const int MAX = 64;

  5. //用来表示每根柱子的信息
  6. struct st{
  7.     int s[MAX]; //柱子上的圆盘存储情况
  8.     int top;     //栈顶,用来最上面的圆盘
  9.     char name;     //柱子的名字,可以是A,B,C中的一个
  10.     
  11.     int Top()    //取栈顶元素
  12.     {
  13.         return s[top];
  14.     }
  15.     
  16.     int Pop()    //出栈
  17.     {
  18.      return s[top--];
  19.     }
  20.     
  21.     void Push(int x)    //入栈
  22.     {
  23.      s[++top] = x;
  24.     }
  25. } ;

  26. long Pow(int x, int y);     //计算x^y

  27. void Creat(st ta[], int n); //给结构数组设置初值

  28. void Hannuota(st ta[], long max);     //移动汉诺塔的主要函数

  29. int main(void)
  30. {
  31.     int n;    
  32.     cin >> n;                     //输入圆盘的个数
  33.     st ta[3];                     //三根柱子的信息用结构数组存储
  34.     Creat(ta, n);                 //给结构数组设置初值
  35.     long max = Pow(2, n) - 1;    //动的次数应等于2^n - 1
  36.     Hannuota(ta, max);            //移动汉诺塔的主要函数
  37.     system("pause");
  38.     return 0;
  39. }

  40. void Creat(st ta[], int n)
  41. {
  42.     ta[0].name = 'A';
  43.     ta[0].top = n-1;
  44.     
  45.     //把所有的圆盘按从大到小的顺序放在柱子A上    
  46.     for (int i=0; i<n; i++)
  47.         ta[0].s[i] = n - i;
  48.     
  49.     //柱子B,C上开始没有没有圆盘
  50.     ta[1].top = ta[2].top = 0;
  51.     
  52.     for (int i=0; i<n; i++)
  53.         ta[1].s[i] = ta[2].s[i] = 0;
  54.     
  55.     //若n为偶数,按顺时针方向依次摆放 A B C    
  56.     if ( n%2 == 0)
  57.     {    
  58.         ta[1].name = 'B';
  59.      ta[2].name = 'C';
  60.     }
  61.     else //若n为奇数,按顺时针方向依次摆放 A C B
  62.     {
  63.         ta[1].name = 'C';
  64.      ta[2].name = 'B';
  65.     }
  66. }

  67. long Pow(int x, int y)
  68. {
  69.     long sum = 1;
  70.     
  71.     for (int i = 0; i < y; i++)
  72.         sum *= x;
  73.     
  74.     return sum;
  75. }

  76. void Hannuota(st ta[], long max)
  77. {
  78.     int k = 0;     //累计移动的次数
  79.       int i = 0;
  80.       int ch;

  81.       while (k < max)
  82.       {
  83.         //按顺时针方向把圆盘1从现在的柱子移动到下一根柱子
  84.         ch = ta[i%3].Pop();

  85.          ta[(i+1)%3].Push(ch);

  86.            cout << ++k << ": " << "Move disk " << ch << " from "
  87.            << ta[i%3].name <<" to " << ta[(i+1)%3].name << endl;

  88.            i++;

  89.            //把另外两根柱子上可以移动的圆盘移动到新的柱子上
  90.            if (k < max)
  91.            {
  92.             //把非空柱子上的圆盘移动到空柱子上,当两根柱子都为空时,移动较小的圆盘
  93.             if (ta[(i+1)%3].Top() == 0 || ta[(i-1)%3].Top() > 0
  94.                 && ta[(i+1)%3].Top() > ta[(i-1)%3].Top())
  95.             {
  96.                 ch = ta[(i-1)%3].Pop();
  97.                 ta[(i+1)%3].Push(ch);
  98.                 cout << ++k << ": " << "Move disk " << ch << " from "
  99.                 << ta[(i-1)%3].name << " to " << ta[(i+1)%3].name << endl;
  100.             }
  101.             else
  102.          {
  103.                    ch = ta[(i+1)%3].Pop();
  104.                    ta[(i-1)%3].Push(ch);
  105.                    cout << ++k << ": " << "Move disk " << ch << " from "
  106.                    << ta[(i+1)%3].name << " to " << ta[(i-1)%3].name << endl;
  107.             }
  108.          }
  109.     }
  110. }




 

 

阅读(12891) | 评论(0) | 转发(1) |
给主人留下些什么吧!~~