函数递归相信大家初学的时候肯定和我一样直冒冷汗,就像盗梦空间里面梦中梦一样烧脑,那么我们如何跳出多层梦境,直接看穿其本质呢?下面我就跟大家分享一些例子和我学习后的心得体会。
最快的方法就是先看一个最简单的递归例子:
int Fun(int n)
{
if(n==5)
return 2;
else
return 2*Fun(n+1);
}
在这里我们定义了一个Fun函数,传递了一个整型变量n,如果n为5就返回值2,如果不为5就返回2倍的Fun(n+1)。如果n = 2的话,简单思考一下这个返回值是多少呢?看起来似乎有点复杂,但我们可以不断拆分 ,如下图:
传入 Fun(2)
第一次返回 2* Fun(3)
第二次返回 2*(2* Fun(4))
第三次返回 2*2*(2* Fun(5))
第四次返回2*2*2*2 == 16
如果这里条件不是五
第n次返回: 2的n次方 *Fun(2+n)
这样是不是清楚多了呢?而且相信大家也有点熟悉这个感觉,和高中数学里面有一个问题非常神似,那就是a(n) = a(n-1)+ a(n-2)+ ...这种变式。理解起来也是一样的,就是由于新变量n带入的函数(数学里的方程)是根据其它与n相关变量(如n-1)代入值进行变化的,所以你需要把每一次计算返回的常数分离,再拆解找规律。下面再给大家一个例题,按照这个想法继续看看有没有多一点思路:
递归和非递归分别实现求第n个斐波那契数
斐波那契数:后一个数是前两个数字之和
1 1 2 3 5 8 13 21....
例如:
输入:5 输出:5
输入:10, 输出:55
输入:2, 输出:1
代码如下图:
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
//递归方法
int member(int n) {
if (n <= 2)
return 1;
else
return member(n - 1) + member(n - 2);
}
int main() {
int n = 0;
printf("请输入所求位数:");
scanf("%d", &n);
int r = member(n);
printf("结果为%d", r);
return 0;
}
这就是数学中a(n)= a(n-1)+ a(n-2)转换成函数递归的实现,在现实生活中有许多按照一定规律或者逻辑反复进行的问题都可以通过函数递归的方式进行实现,下面再给大家两个练习(最下面附代码):
1. 递归方式实现打印一个整数的每一位:如输入1996,打印 1 9 9 6
2.递归和非递归分别实现求n的阶乘(不考虑溢出的问题)
这里还有几个需要提醒大家注意的事项:一个是递归需要有条件限制,不然就会死循环下去。这个大家很容易理解,完成一个事情肯定有终点。另一个就是函数递归层次太深,会出现栈溢出现象。由于每一次函数调用都会开辟一块地址空间作为这个函数的栈帧,而递归结束前之前开辟的函数栈帧不会消除,所以如果递归过多,导致栈帧数量过多,就可能发生栈的空间不足,进一步导致栈溢出。
总之函数递归是一个能够把大量重复代码简化的最佳方式,如果你还有哪些不懂欢迎私信我或者留言和其他小伙伴讨论哦~谢谢大家的观看,Fish-Yan写完这篇的同时学完了指针,喜欢的同学可以点点关注,下一篇“从0开始的指针生活!”
1.的答案:
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
void print(int a) {
if (a > 9)
print(a / 10);
printf("%d ", a % 10);
}
int main() {
int n = 0;
printf("֣");
scanf("%d", &n);
print(n);
return 0;
}
2.的答案
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
//递归法
int fact(int a) {
if (a == 0)
return 1;
else if (a > 0)
return a * fact(a - 1);
}
int main() {
int n = 0;
printf("请输入你要求的阶乘:");
scanf("%d", &n);
int r = fact(n);
printf("计算结果为:%d", r);
return 0;
}