C语言递归实现n阶汉诺塔操作过程

汉诺塔(Tower of Hanoi)是一个源于印度古老传说的益智玩具。基本规则很简单,有三个立柱,然后在最左边放着n个盘子叠成的“塔”,要求把所有盘子移到最右边的柱子,一次只能移动一个盘子,并且不能从中间抽出盘子,即只能拿最上面的盘子,并且移动盘子过程中需始终遵循大盘子在小盘子下面的原则。
程序要求:已知三根柱子从左到右依次标号A、B、C。输入一个正整数n,表示最左边的柱子一开始盘子的个数,盘子初始状态也遵循大盘子在小盘子下面的原则,并且盘子从小到大依次标号为1、2、…、n。要求打印出每次对盘子的操作,并且每次操作单独占一行,比如:把柱子A最上面的标号为i的盘子移动到柱子B上,即打印“Move plate i from A to B.",操作结束后,要求打印操作的次数。
思路:
本文用递归实现操作过程,因此要思考递归实现问题的基本思路:大问题化小问题。递归是一种经典的分治算法思想,将大问题化为若干小问题解决。因此我们想到,如果要把A柱的n层塔移动到C柱,必须要把编号为n的盘子从A移动到C,而要移动编号为n的盘子,必须把标号为1到n-1的盘子移开,不然n号盘我们动不了,而且1号到n-1号盘子都必须在B柱,因为我们的n号盘要放在C柱的最底下,又因为盘子的叠放要遵循大盘子始终在小盘子下面的原则,因此这n-1个盘子均叠放在B柱并且是从小到大叠放的,即我们把一个n-1阶的汉诺塔从A柱移动到了B柱。
在这里插入图片描述

看到这里可能有些读者已经明白了这个算法的实现过程。我们把三根柱子分成出发柱、过程柱、目的柱。比如我们的初始问题,把n阶汉诺塔从A柱移动到C柱,那么A柱就是出发柱,C柱就是目的柱,B柱就是我们的过程柱,我们要借助这个过程柱实现我们的搬运过程。我们要实现n阶汉诺塔的移动,就得先把n-1阶的汉诺塔从A柱移动到B柱,然后把第n号盘从A柱移动到C柱,再把n-1阶的汉诺塔移动到C柱。
在这里插入图片描述
在这里插入图片描述
而对于n-1阶汉诺塔从A到B的移动,出发柱还是A,但是目的柱变成了B,过程柱变成了C,即利用C把盘堆从A移动到B,后来把n-1阶汉诺塔从B到C的移动,出发柱成了B,目的柱变成了C,过程柱变成了A。而n-1阶汉诺塔的移动又变成了n阶汉诺塔的移动,只是这个n变成了n-1。所以我们在编程中要给递归函数出发柱、过程柱、目的柱描述此时的过程。因此思路是这样,下面上代码:

#include<stdio.h>
int cont=0;//用来记录操作次数,此处使用全局变量
void Hanoi(int n,char start,char end,char process)//此处标识符的使用是为了便于读者理解,实际使用时可以适当简化
{
    cont++;
    if(n==1)//只剩最后一个盘子(即1号盘)时,直接移动即可
    {
        printf("Move plate 1 from %c to %c.\n",start,end);
        return;
    }
    else
    {//此大括号内的目的、过程、出发都是对本次函数体内的移动过程而言,即对此时n个盘子的移动过程而言
        Hanoi(n-1,start,process,end);//将n-1阶汉诺塔从出发柱移动到过程柱,通过目的柱
        printf("Move plate %d from %c to %c\n",n,start,end);//将最下面的大盘子从出发柱直接移动到目的柱
        Hanoi(n-1,process,end,start);//将n-1阶汉诺塔从过程柱移动到目的柱,通过出发柱
    }
}
int main(){
    char a='A',b='B',c='C';
    int n;
    printf("Now tell me how much plates you want to move?\n")
    scanf("%d",&n);
    Hanoi(n,a,c,b);//把n个盘子从A柱移动到C柱,借助B柱
    printf("There are %d moves in total.\n",cont);
    return 0;
}

  • 6
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值