汉诺塔的递归和非递归实现

 汉诺塔的递归和非递归实现 

借助堆栈以非递归(循环)方式求解汉诺塔的问题(n, a, b, c),即将N个盘子从起始柱(标记为“a”)通过借助柱(标记为“b”)移动到目标柱(标记为“c”),并保证每个移动符合汉诺塔问题的要求。

输入格式:

输入为一个正整数N,即起始柱上的盘数。

输出格式:

每个操作(移动)占一行,按柱1 -> 柱2的格式输出。

输入样例:

3

输出样例:

a -> c
a -> b
c -> b
a -> c
b -> a
b -> c
a -> c

代码:(递归算法)
ps:函数hanoi里的n是n个盘子,move函数里的n是第n个
 1 #include <stdio.h>
 2 int i=1;//记录步数
 3 void move(int n,char x,char y) //将编号为n的盘子由from移动到to
 4 {
 5     printf("将%d号盘子%c---->%c\n",n,x,y);
 6 }
 7 void hanoi(int n,char x,char y,char z)//将n个盘子由初始塔移动到目标塔(利用借用塔)
 8 {
 9     if (n==1)
10         move(1,x,z);//只有一个盘子是直接将初塔上的盘子移动到目的地
11     else
12     {
13         hanoi(n-1,x,z,y);//先将初始塔的前n-1个盘子借助目的塔移动到借用塔上
14         move(n,x,z);              //将剩下的一个盘子移动到目的塔上
15         hanoi(n-1,y,x,z);
16         //最后将借用塔上的n-1个盘子移动到目的塔上
17     }
18 }
19 int main()
20 {
21     printf("请输入盘子的个数:\n");
22     int n;
23     scanf("%d",&n);
24     char x='A',y='B',z='C';
25     printf("盘子移动情况如下:\n");
26     hanoi(n,x,y,z);
27     return 0;
28 }
 
 

递归的算法,简洁一点也可以这样写:

void Hanoi(int n,char A,char B,char C)  //A借助B,将n个盘子移到C ,递归的妙用在于不用关心具体实现的细节
{
    if (n==1)printf("%c -> %c",A,C); //只有一个盘子,直接将其移到C
    else
    {
        Hanoi(n-1,A,C,B);  //第一步,A借助C,将n-1个盘子移到B;
        printf("%c -> %c",A,C);   //第二步,将A上剩余的一个盘移到C;
        Hanoi(n-1,B,A,C)  //第三步,将B上的n-1个盘子移到C。
    }
}

 

 

 

坦白说,关于非递归的算法,没什么思路,就是用递归算法跑一些数值,想出来的算法也不是特别好

 

代码:(非递归算法)

 

 1 #include<iostream>  
 2 #include<algorithm>  
 3 #include <stack>  
 4 #include <cstdio>  
 5 #include<cmath>  
 6 using namespace std;  
 7 int temp1=-1, temp2=-1;  
 8 char s[4] = { 'q','a','b','c' };//为了解题简便,我是从1开始算的  
 9 stack<int> a[4];  
10 int c1 = 0;  
11 int rank1[4];  
12 bool compare(int a1,int b1) 
13 { //给栈顶元素排序用  
14     if (a[a1].top() >= a[b1].top())  
15         return true;  
16     if (a[a1].top() < a[b1].top())  
17         return false;  
18     return false;  
19 }  
20 bool move1(int before,int after) {   //移动物块  
21     if ((a[after].top() - a[before].top())%2==0)  
22         return false;  
23     a[after].push(a[before].top());  
24     a[before].pop();  
25     temp1 = before; temp2 = after;  //记录上一次移动的物块位置  
26     printf("%c -> %c\n",s[temp1],s[temp2]);
27     c1++;  
28     return true;  
29 }  
30 int main(){  
31     int i, N;  
32     cin >> N;//起始柱上的盘数
33     a[1].push(N+1);//保证栈不会为空  
34     for (i = 0; i < N; i++)  
35         a[1].push(N-i);   //初始化  
36     a[2].push(N + 2);  
37     a[3].push(N+3);  
38     if (N % 2 == 1) {        //N为奇数还是偶数,第一次移物块到哪里是不同的  
39         move1(1, 3);  
40         temp1 = 1;  
41         temp2 = 3;  
42     }  
43     else {  
44         move1(1, 2);  
45         temp1 = 1; temp2 = 2;  
46     }  
47     for (i = 1; i <= 3; i++)//初始化栈排序表  
48         rank1[i] = i;  
49     int tt;  
50     while (c1 < pow(2, N) -1) {  
51         sort(rank1 + 1, rank1 + 4, compare);//按compare函数排序  
52             if (temp2 == rank1[2]) { //刚移动过的物块不会再被移动  
53                 if(tt==temp1)   //别问我为什么,找规律找出来的  
54                     move1(rank1[3], rank1[2]);  
55                 else  
56                     move1(rank1[3], rank1[1]);  
57             }  
58             else  
59                 move1(rank1[2], rank1[1]);  
60         tt = rank1[2];   
61     }  
62 }  

 

转载于:https://www.cnblogs.com/guohaoyu110/p/6360120.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值