1.前言
承接上一篇博客,我们对递归的基本概念和基本用法做了最基础的介绍与讲解,接下来我们继续分享递归其他经典简单的应用。
2.俩个递归例题
1.青蛙跳台阶问题
题目如下:有一只小青蛙,现在在第0个台阶,已知它可以一次跳一个台阶,也可以一次俩个台阶,如果小青蛙要跳n个台阶,请问有多少种跳法。
老样子先附上代码
#include <stdio.h>
int func(int m) {
if (m == 1) {
return 1;
}
else if (m == 2) {
return 2;
}
else{
return func(m - 1) + func(m - 2);
}
}
int main()
{
int n = 0;
scanf_s("%d", &n);
int num = func(n);
printf("%d %d", n, num);
return 0;
}
小青蛙跳n个台阶,逐一列举很显然是不合适的,通过递归的基本思想可以有以下思路。当有一个台阶的时候,跳法自然只有一种;当有俩个台阶的时候,跳法一共有俩种(跳俩个一个台阶或跳一个俩个台阶)。当台阶数大于2时,可以按照如下图理解(伪代码):
func(n)=func(n-1)+func(n-2)
func(n-1)=func(n-2)+func(n-3)
func(n-2)=func(n-3)+func(n-4)
我建立了一个被调用函数(如图),假设小青蛙还剩最后一步就可以跳到第n个台阶,有俩种可能,即位于(n-1)和(n-2)个台阶,则跳到第n个台阶的跳法为跳到第(n-1)个台阶和跳到第(n-2)个台阶上方法的加和,以此类推往下层层展开,即可得解,下面拿n为5举个例子:
func(5)=func(4)+func(3)
=func(3)+func(2)+func(2)+func(1)
=func(2)+func(1)+func(2)+func(2)+func(1)
递归到最后,就会回到跳1,2台阶的跳法上面。以上则是小青蛙跳台阶的题解与思路解析。
2.汉诺塔问题
汉诺塔(Tower of Hanoi),又称河内塔,是一个源于印度古老传说的益智玩具。大梵天创造世界的时候做了三根金刚石柱子,在一根柱子上从下往上按照大小顺序摞着64片黄金圆盘。大梵天命令婆罗门把圆盘从下面开始按大小顺序重新摆放在另一根柱子上。并且规定,在小圆盘上不能放大圆盘,在三根柱子之间一次只能移动一个圆盘。(上文摘自百度百科)
题目如下:有三根相邻的柱子,标号为A,B,C,A柱子上从下到上按金字塔状叠放着n个不同大小的圆盘,要把所有盘子一个一个移动到柱子C上,并且每次移动同一根柱子上都不能出现大盘子在小盘子上方(即在迁移的过程中小盘必须在大盘上上方),请问至少需要多少次移动,才能将所有的圆盘按顺序移到C柱。
1.一个圆盘时(图解)
当只有一个圆盘的时候,显而易见从A到C只需要移动一次(不要忽视最简单的第一层,后面会讲解原因)。
2.俩个圆盘时(图解)
当只有俩个圆盘的时候,为了方便描述,从上到小编号1~2,1先到B,然后2到C,最后B位置的1移到C,移动共计3次。
3.三个圆盘时(图解)
当有三个圆盘的时候,情况就开始复杂了,从上到下编号1~3,1到C,2到B,1再到B(此时1和2都已经在B上),然后再将3移到C,1到A,2到C,最后1再到C,至此已经全部移动完毕,共计七次。不知道大家有没有发现,本次移动是先将最上面俩个移到B,再将三个都移到C上(其实俩个圆盘的时候也是如此,先把2上面那个1移到B,再将俩个都移到C)
4.n个圆盘时
我们观察上面三个特例,运用特殊到一般的数学思想进行分析不难发现,如果我们将n个圆盘移到C时(当n大于等于2的时候),先需要将n-1个圆盘都先移动B,再将第n个圆盘移到C,再将n-1个圆盘移到C上。
由此我们的代码可得:
#include <stdio.h>
void move(char p1, char p2) {
printf("%c->%c/n", p1, p2);//用来打印出来每一次移动,p为缩写的position,通过p1,p2,p3表示ABC
}
void hanoi(int m, char p1, char p2, char p3) {
if (m == 1) {
move(p1, p3);
}
else {
hanoi(m - 1, p1, p2, p3);//先将n-1移到B
move(p1, p3);//再将n移到C
hanoi(m - 1, p2, p1, p3);//最后再将n-1移到C
}
}
int main()
{
int n = 0;
scanf_s("%d", &n);
hanoi(n, 'A', 'B', 'C');
return 0;
}
以上代码就可以将汉诺塔每一步移动都复现出来咯。
3.总结
上述俩个例题都很好的反应了递归的思想,同时也运用到了函数的调用,希望对大家有帮助。