汉诺塔之递归算法

*庸庸碌碌的过了这么久,代码还是一如既往的不会写,希望这次真的是一个新的开始,递归这个东西真的让我头疼,好难转过这个弯来,纠结了这么多天终于写会了汉诺塔的小问题。

【汉诺塔】

有三个柱子,分别为 a , b ,c ,在 a 上有 n 个盘子,试问如何才能借助 b 使所有的盘子从 a 移动到 c 柱上,要求每次只能移动一个盘子,小盘子总在大盘子之上,请求解具体的搬运方法

【分析】

设 n 个盘子的序号从小到大为 1~n

一、假设 n = 1:

直接将 盘子从 a 移动到 c,结束。

二、假设 n = 2:

a 上有两个盘子,要想把两个盘子从a 移到 c,需要借助于 b ,分为三步:

(1)先把 1 号盘从 a 移到 b 柱

(2)再将 2 号盘从 a 移到 c柱

(3)最后将1 号盘从 b 柱移到 c 柱,结束。

三、假设 n = 3:

类似于 n = 2 的情况,也需要分三步进行:

(1)把 1 号 2 号 盘从 a 柱移到 b 柱。<源柱、中间柱、最终柱:a 、c 、b;>

(2)把 3 号盘从 a 柱移到 c 柱。       

(3)把 1号 2 号盘从 b 柱移到 c 柱。  <源柱、中间柱、最终柱:b 、a 、c;>

总结代码为:

void f(int n,char a,char b,char c)
{
    if(n==1){    //如果盘数为 1,就不用借助中间柱,直接移动即可完成
       printf("第%d个圆盘:%c->%c\n",n,a,c);
    }
    else     //如果盘数大于 1,需要借助中间柱暂时存放前 n-1 个盘
    {
        f(n-1,a,c,b);       //先将前 n-1个盘 从a 移到 b,必要时需要 c 的帮助
        printf("第%d个圆盘:%c->%c\n",n,a,c);    //前n-1个盘都移到中间柱,那最大的、即第n个便可以顺利的移到最终柱 c上
        f(n-1,b,a,c);      // 第n个已经到位,此时需要将放在中间柱上的n-1个盘移动到最终柱上即可完成。
    }
}

自我理解:汉诺塔的递归程序中,我们写出来的部分就是最外层的一个循环,将 n-1个盘移到中间柱,将第n个移到最终柱,将n-1个移到最终柱。

那么第一步和第三步可以进一步变为n-1个盘子的汉诺塔问题,如此递归下去,计算机自行执行重复的步骤,知道递归到 3个盘子、2个盘子、1个盘子,结束。这个问题就能体现出计算机的好处、递归的好处,一个复杂的问题就转化为一层一层简单的问题知道最简。

【代码】

#include <stdio.h>
#include <stdlib.h>
void f(int n,char a,char b, char c);
int main()
{
    int n;
    printf("请输入数字n以解决汉诺塔问题:\n");
    scanf("%d",&n);
    f(n,'a','b','c');
    return 0;
}

void f(int n,char a,char b,char c)
{
    if(n==1){
       printf("第%d个圆盘:%c->%c\n",n,a,c);
    }
    else
    {
        f(n-1,a,c,b);
        printf("第%d个圆盘:%c->%c\n",n,a,c);
        f(n-1,b,a,c);
    }
}


猜你喜欢

转载自blog.csdn.net/MyCodeQueen/article/details/48971501