PTA 7-17 汉诺塔的非递归实现 (25 point(s))

 借助堆栈以非递归(循环)方式求解汉诺塔的问题(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
#include <bits/stdc++.h>

void Hanoi(int n, char a, char b, char c){
    if(1 == n){   //可以直接移动
        printf("%c -> %c\n", a, c);
    }else{  
        Hanoi(n-1,a,c,b);   //第一步 1~n-1号盘,从a柱移到b柱上
        Hanoi( 1 ,a,b,c);   //第二步 直接将n号盘,从a柱移到c柱上
        Hanoi(n-1,b,a,c);   //第三步 1~n-1号盘,从b柱移到c柱的n号盘上
    }
}   //其实也可以第二步替换为   printf("%c -> %c\n",a,c);   只是为了描述原理,统一更方便

main() {
    int N;
    scanf("%d", &N);
    Hanoi(N,'a','b','c');
}

cout << a << " -> " << c << endl;

这里用cout在PTA平台上输出会超时,即便加上 ios::sync_with_stdio(false) 和 cin.tie(0) 并没有解决问题,不晓得为什么,所以改成了 scanf 和 printf。

//非递归实现
#include<bits/stdc++.h>

//测试点3 的N最大,达到20
#define MAX_N 20    
//恰好能够解决问题的栈容量。
//如N=4时, 栈s最满时的Stack.n分别为[3,1,2,1,1,1,1 ] ;以此类推 N=n时为:[n-1,1,n-2,1,n-3,1,...,3,1,2,1,1,1,1]
#define MAX_SIZE (2*(MAX_N)-1)  


typedef struct{
    char n,a,b,c;
}Stack;

Stack s[MAX_SIZE];   //栈
int top=-1; //栈顶指针

void push(char n,char a,char b,char c){
#define PUSH_S(x) s[top].x=x
    ++top;
    PUSH_S(n);
    PUSH_S(a);
    PUSH_S(b);
    PUSH_S(c);
}

main() {
    int N;
    scanf("%d",&N);
    
    push(N,'a','b','c');    //初始状态
    
    while(top>=0){
        //弹出元素
        Stack TOP = s[top]; --top; 
        
        if(1==TOP.n){   //可以直接移动
            printf("%c -> %c\n",TOP.a,TOP.c);
        }
        
        else{
            //注意栈是先入后出的,递归按照实际操作顺序执行,按顺序不断拆解步骤直到任务完成
            //入栈会把最初的元素压入栈底,而top栈顶指针从上往下顺序弹出并执行任务
            //比如按顺序递归顺序压入栈的话 1 2 3(top) 那么最先执行的就是第三步而不是第一步 
            //故入栈顺序和调用递归函数顺序颠倒 按反顺序入栈 3 2 1(top) 这样就能够按实际操作顺序执行
            
            push(TOP.n-1, TOP.b ,TOP.a ,TOP.c);  //第三步 1~n-1号盘,从b柱移到c柱的n号盘上
            push(1      , TOP.a ,TOP.b ,TOP.c);  //第二步 直接将n号盘,从a柱移到c柱上
            push(TOP.n-1, TOP.a ,TOP.c ,TOP.b);  //第一步 1~n-1号盘,从a柱移到b柱上
        }
    }
}
//非递归实现 改成用自带的stack 
//不需要自己移动栈顶指针 不需要自己计算堆栈容量 除此以外操作没什么差别
#include<bits/stdc++.h>
using namespace std;

typedef struct{
    char n, a, b, c;
}Hanoi;

stack<Hanoi> s;

Hanoi hanoi(char n, char a, char b, char c){
    Hanoi tmp;
    tmp.n = n;
    tmp.a = a;
    tmp.b = b;
    tmp.c = c;
    return tmp;
}

main() {
    int N; 
    scanf("%d", &N);
    
    s.push(hanoi(N, 'a', 'b', 'c'));
    
    while(!s.empty()){
        Hanoi TOP = s.top();
        s.pop();
        
        if(TOP.n == 1){
            printf("%c -> %c\n", TOP.a, TOP.c);
        }
        
        else{
            s.push(hanoi(TOP.n - 1, TOP.b, TOP.a, TOP.c));
            s.push(hanoi(1        , TOP.a, TOP.b, TOP.c));
            s.push(hanoi(TOP.n - 1, TOP.a, TOP.c, TOP.b));
        }
    }
}

 参考代码        递归和堆栈

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值