一.函数递归
1.定义
在一种计算过程,如果其中每一步都要用到前一步或前几步的结果,称为递归。用递归过程定义的函数,称为递归函数。在编程语言中,函数Func()直接或间接调用函数本身,则该函数称为递归函数。
使用了递归后,我们就可以做很多事情了,例如连加、连乘及阶乘等,凡是递归的函数,都是可以计算的。
下图为函数递归调用的图示
2.函数递归的优缺点
优点
递归的优点显而易见,代码简洁,可读性高,可维护性也高,有时候几百行的代码如果使用递归几十行就可以解决,递归还可将较复杂的问题化为比较小的问题,化繁为简。
缺点
递归最重要的就是需要避免死循环的出现和逻辑关系的正确性递归,我们在使用递归的时候,要避免死递归和逻辑错误,然后还有调试困难,运行时占用内存大,运行效率低,调用栈溢出等缺点
二.斐波那契数列
我们接下来实现斐波那契数列,斐波那契数列是以兔子繁殖为例子而引入,故也称兔子数列
递推公式
斐波那契数列:1,1,2,3,5,8,13,21,34,55,89…
斐波纳契数列以如下被以递归的方法定义:
这个数列从第三项开始,每一项都等于前两项之和
我们展示两个版本
非递归代码展示
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
int func(int n)
{
int a = 1, b = 1, sum = 1;
if (n == 1 || n == 2)
{
return 1;
}
else
{
while (n >= 3)
{
sum = a + b;
a = b;
b = sum;
n--;
}
return sum;
}
}
int main()
{
int n = 0;
scanf("%d", &n);
printf("%d\n", func(n));
return 0;
}
递归代码展示
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
int func(int n)
{
if (n == 1 || n == 2)
{
return 1;
}
else
{
return func(n - 1) + func(n - 2);
}
}
int main()
{
int n = 0;
scanf("%d", &n);
printf("%d\n", func(n));
return 0;
}
两种方式的区别
实际运行时候会发现,输入一个比较大的数字时候,非递归代码运行的效率是远大于递归代码的,实际大家可以体验一下,注意数据过大可能不会出现正确结果,因为这里使用的是整型数据,结果是有范围的。
三.阶乘
定义
一个正整数的阶乘(factorial)是所有小于及等于该数的正整数的积,并且0的阶乘为1。
亦即n!=1×2×3×…×(n-1)×n,阶乘亦可以递归方式定义:0!=1,n!=(n-1)!×n。
非递归代码展示
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int fact(int n)
{
if ("n>=0")
{
int ret = 1;
for (int i = 1; i <= n; i++)
{
ret *= i;
}
return ret;
}
}
int main()
{
int n = 0, ret = 1;
scanf("%d", &n);
printf("%d", fact(n));
return 0;
}
递归代码展示
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
int fact(int n)
{
int sum = 0;
if (n == 1)
{
return 1;
}
else
{
return sum = n * fact(n - 1);
}
}
int main()
{
int n = 0;
scanf("%d", &n);
printf("%d", fact(n));
return 0;
}
难点解疑
我们举个例子,假设我们求的是5!,那么上述fact () 运行图解如下(红色为递推阶段,绿色为回归阶段)
4!就是4乘以3!,3!就是3乘以2!,以此类推,我们只需返回n乘以(n-1)!即可,(n-1)!怎么算呢,我们只需要再调用一次函数,返回值为(n-1)乘以(n-2)!,以此类推我们就可以算出n的阶乘啦
四.尾声
- 本文章展示的函数递归只是一些简单的例子,大家可以自己去尝试一下更难的递归,欢迎大家的交流讨论相关知识。
- 如果上述内容有错误,请大家及时指出