函数递归:汉诺塔问题

1.问题描述

      汉诺塔问题是一个古典的数学问题,它只能用递归方法来解决。在古代有一个梵塔,塔内有A、B、C三个座。开始时A座上有64个盘子,盘子大小不同,但保证大的在下小的在上。现在有一个和尚想将这64个盘子从A座移动到C座,但他每次只能移动一个盘子,且在移动过程中在3个座上都必须保持大盘在下小盘在上的状态。在移动过程中可以利用B座,要求编程将移动步骤打印出来。

2.问题分析

      具体步骤如下。

   (1)将A座最上面的63个盘子移动到B座上。

   (2)将A座上剩下的一个盘子移动到C座上。

   (3)将B座上的63个盘子移动到C座上。

      如果能完成上述3步,则任务完成。这种思考方法就是递归的思考方法。但实际上问为了解决将A座最上面的63个盘子移动到B座上的问题,还需要做如下工作。

    (1)将A座上面的62个盘子移动到C座上。

    (2)将A座上剩下的一个盘子移动到B座上。

    (3)将C座上的62个盘子移动到B座上。

      将这个过程进行下去,即不断的递归,继续完成移动62个盘子、61个盘子·····工作,直到最后将达到仅有一个盘子的情形,则将一个盘子从一个座移动到另一个座,问题也就全部得到了解决,所有的步骤都是可执行的。

      要说明的是,只有移动一个盘子的任务完成后,移动两个盘子的任务才能完成,依次类推,只有移动63个盘子的任务完成后,移动64个盘子的任务才能完成,由此可知该问题是非常典型的递归问题。

3.算法设计

        该问题使用递归算法来解决。由于递归算法具有如下的特征:为了求解规模为N的问题,应先设法将该问题分解成一些规模较小的问题,从这些较小问题的解可以方便地构造出大问题的解。同时,这些规模较小的问题也可以采用同样的方法分解成规模更小的问题,并能从这些规模更小的问题的解中构造出规模较小问题的解。特别地,当N=1时,可直接获得问题的解。

       现在给出解决问题的方法。

       先定义递归函数hanio(int N,char A,char B,char C),该函数表示将N个盘子从A座借助B座移动到C座,盘子的初始个数为N.下面是解题步骤:

       若A座上只有一个盘子,此时N=1,则可直接将盘子从A座移动到C座上,问题解决。

       若A座上有一个以上的盘子,即N>1,此时需要再考虑三个步骤。

    (1)将N-1个盘子从A座借助C座先移动到B座上。显然,这N-1个盘子不能作为一个整体移动,而是要按照要求来移动。此时,可递归调用方法hanio(N-1,A,C,B),需要注意的是,这里是借助C座将N-1个盘子从A座移动到B座,A是源,B是目标。
    (2)将A座上剩下的第N个盘子移动到C座上。

    (3)将B座上的N-1个盘子借助于A座移动到C座上。此时,递归调用方法 hanio(N-1,B,A,C),此时,借助A座,将N-1个盘子从B座移动到C座。

       完成了这3步,就可以实现预期的效果,在C座上正确地按次序叠放好所有的盘子。

4.完整程序

#include <stdio.h>
void hanoi(int n,char A,char B,char C)
{
    if(n==1)
    {
        printf("Move dish %d from %c to %c\n",n,A,C);
    }
    else
    {
        hanoi(n-1,A,C,B);
        printf("Move dish %d from %c to %c\n",n,A,C);
        hanoi(n-1,B,A,C);
    }
}
int main(void)
{
    int n;
    scanf("%d",&n);
    hanoi(n,'A','B','C');
    return 0;
}

5.运行结果

      

  • 23
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值