首页 > 其他 > 详细

从一些例子想想解决递归问题的思路

时间:2020-07-16 23:32:27      阅读:78      评论:0      收藏:0      [点我收藏+]

之前遇上的递归问题都比较简单,至少都有一个明确的切入点,例如随机生成迷宫、扫雷等,通常都是从一点开始向外扩展,那一点就是切入点。

直到碰上汉诺塔问题,两眼一抹黑,没有思路。还是靠看别人的思路才解决的。

打算以后碰上新的递归问题,都把思路写一写。

1、汉诺塔

汉诺塔问题概述就不写了
假设共有n个圆盘在A柱(圆盘当前所在柱)上,B(中间柱)、C(目标柱)柱上暂时空空如也,想要把n个圆盘全部移到C柱上。

由于汉诺塔问题的限制导致势必有那么一个时刻,前n-1个圆盘从A柱转移到了B柱上,此时n号圆盘才能离开A柱到达C柱,对于留在B柱上的n-1个圆盘最终也要转移到C柱。

于是问题分为三步:1、前n-1个圆盘从A柱转移到B柱

          2、n号圆盘从A柱转移到C柱

          3、前n-1个圆盘从B柱转移到C柱

2好说,主要问题是1、3。

1、前n-1个圆盘从A柱转移到B柱

  由于第n个圆盘比其他所有盘子都大,对于圆盘的转移没有任何影响,所以这个问题与汉诺塔本身相比除了圆盘少了一个(n到n-1),终点柱子变了(C柱变B柱)以外,没有任何区别,甚至可以看做是另一个汉诺塔问题。

  那么按照之前的思路有:1.1、前n-2个圆盘从A柱转移到C柱

              2.2、n-1号圆盘从A柱转移到B柱

              2.3、前n-1个圆盘从C柱转移到B柱

3、问题也是同理有:3.1、前n-2个圆盘从B柱转移到A柱

          3.2、n-1号圆盘从B柱转移到C柱

          3.3、前n-1个圆盘从A柱转移到C柱

既然问题分支的解决方法与问题本身几乎一致,那就可以考虑下递归能否解决了。

如果现在搭一个递归的架子,那大概是这样:

void hanion(int n ,xxxxxxxx)//n个圆盘的转移
{
    hanion(--n,xxxxxxx);//n-1个圆盘的转移
    printf("第%d个圆盘从xxxx柱---->xxxx柱",n,xxxxx,xxxxx);//n号圆盘的转移
    hanion(--n,xxxxxxx);//n-1个圆盘的转移
}

一个大概的样子有了,那怎么让这个函数知道这些圆盘当前在哪根柱子上,接下来又要去那根柱子上呢?

我们观察1、2、3            以及          1对应的1.1、1.2、1.3            还有3对应的3.1、3.2、3.3  可以发现

 

任何一个x个圆盘的转移问题,如果按上述思路分为三步,那么其:

         圆盘当前所在柱(A)  会成为 第1、2步的   圆盘当前所在柱

         中间柱(B)    会成为第1步的    目标柱    和第3步的     圆盘当前所在柱

       目标柱(C)    会成为 第1、2步的      目标柱

 

不管函数嵌套到何种程度,这个关系都不会改变,只要将这个关系写入函数声明,在后续的递归执行中就能正确表示圆盘的位置与转移关系了。

 

可以定义三个形参a,b,c,用它们代表圆盘当前所在柱、中间柱、目标柱。

void hanion(int n ,char  a,char b,char c)//n个圆盘的转移

 

那么按照之前得到的规律,函数定义会变成:

void hanion(int n ,char  a,char b,char c)//n个圆盘的转移
{
    hanion(--n,a,c,b);//n-1个圆盘的转移
    printf("第%d个圆盘从%c柱---->%c柱",n,a,c);//n号圆盘的转移
    hanion(--n,b,a,c);//n-1个圆盘的转移
}

 

现在函数还缺一个可靠的出口,显然光靠一个return 并不行。

针对n,容易想到这玩意儿小于1就没有意义了,所以要加上:

if(n==1)
    return;

 

它需要加在当前所写的函数定义的开头位置,否则无法阻止递归的进行,但要注意既然写在printf语句前,那么这段程序就不会执行了,而它想输出的是  “第1个圆盘从xxx柱--->xxx柱”,这是有用的。

所以要在if语句中加上   printf("第1个圆盘从%c柱--->%c柱",a,c); 或printf("第%d个圆盘从%c柱--->%c柱",n,a,c);(此时n就是1)  ,改为:

void hanion(int n ,char  a,char b,char c)//n个圆盘的转移
{
    if(n==1)
    {
        printf("第1个圆盘从%c柱--->%c柱",a,c);
        return 0;
    }
    hanion(--n,a,c,b);//n-1个圆盘的转移
    printf("第%d个圆盘从%c柱--->%c柱",n,a,c);//n号圆盘的转移
    hanion(--n,b,a,c);//n-1个圆盘的转移
}

 

从一些例子想想解决递归问题的思路

原文:https://www.cnblogs.com/skyrim-Dragonborn/p/13325253.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!