函数递归
什么是递归
递归其实是⼀种解决问题的⽅法,在C语⾔中,递归就是函数⾃⼰调⽤⾃⼰。写⼀个史上最简单的C语⾔递归代码:
#include <stdio.h>
int main()
{
printf("hehe\n");
main();//main函数中⼜调⽤了main函数
return 0;
}
当然这仅仅是演示递归的一种形式,此代码最终会陷入一种死循环。
递归举例
举例1:求n的阶乘
首先我们要知道什么是阶乘:
- 对于所有非负整数n,n!的定义是:
n = 0 时,n!= 1;
-
n > 0 时,n! = n×(n−1)!;
这个定义意味着:
- 0的阶乘是1,即 0!=1。
- 1的阶乘也是1,即 1!=1。
- 对于任何大于1的整数n,n的阶乘是n乘以n-1的阶乘,即 n!=n×(n−1)!。
下面代码演示
int Fact(int n)
{
if(n = 0)
return 0;
else
return n * Fact(n - 1);
}
int main()
{
int n;
scanf_s("%d\n", &n);
int Ret = Fact(n);
printf("%d\n", Ret);
return 0;
}
在第一段代码中我们写了一段阶乘函数;在主函数中进行调用。
举例二:顺序打印一个整数的每一位
比如:
输入:1234 输出:1 2 3 4
对此,我们进行分析:
1234%10 —> 4 我们再对 1234/10—>123;这就相当于去掉了4;
以此类推,我们依次可以得到 4 3 2 1
但是这与我们想要的结果是相反的,对此我们可不可以想一个办法解决呢?
void Print(int n)
{
if (n > 9)
{
Print(n / 10);
}
printf("%d", n % 10);
}
int main()
{
int n;
scanf_s("%d", &n);
Print(n);
return 0;
}
当输入1234时,进入Print,1234是>9的,再进入Print,直到最后打印1,打印1之后,再返回到上一个if语句,打印2,以此类推,我们可以不断打印1 2 3 4。
当然并不是都要用递归解决问题。
例如:求第n斐波那契数。
同样我们先了解什么是斐波那契数:
每个数是前两个数的和,数列的前两个数定义为0和1。因此,斐波那契数列的前几项是:0, 1, 1, 2, 3, 5, 8, 13, 21, 34, ...
根据我们之前举得例子,对于斐波那契数我们很容易写成递归的形式
int Fit(int n)
{
if (n <= 2)
return 1;
else
return Fit(n - 1) + Fit(n - 2);
}
int main()
{
int n;
scanf_s("%d", &n);
int ret = Fit(n);
printf("%d\n", ret);
return 0;
}
但是当我们以这个代码来完成任务的时候,我们会发现当输入的数值较大时,运算时间会较长,效率低,我们可以添加一个count来看看:
int count = 0;
int Fit(int n)
{
if (n == 3)
count++;
if (n <= 2)
return 1;
else
return Fit(n - 1) + Fit(n - 2);
}
int main()
{
int n;
scanf_s("%d", &n);
int ret = Fit(n);
printf("%d\n", ret);
printf("count = %d\n", count);
return 0;
}
当我们输入某个值时,我们便可以看出第三个数被重复计算了多少次
我们可以对此代码进行优化
int Fit(int n)
{
int a = 1;
int b = 1;
int c = 1;
while (n > 2)
{
c = a + b;
a = b;
b = c;
n--;
}
return c;
}
int Fit(int n)
{
int a = 1;
int b = 1;
int c = 1;
while (n > 2)
{
c = a + b;
a = b;
b = c;
n--;
}
return c;
}
int main()
{
int n;
scanf_s("%d", &n);
int ret = Fit(n);
printf("%d\n", ret);
return 0;
}
拓展
青蛙跳台阶
汉诺塔
关于这两个问题我们直接给出代码
int Func(int n)
{
if (n == 1)
return 1;
if (n == 2)
return 2;
else
return Func(n - 1) + Func(n - 2);
}
int main()
{
int n = 0;
scanf_s("%d", &n);
int Set = Func(n);
printf("%d", Set);
return 0;
}
int count = 0;
void Hant(int n, char a, char b, char c)
{
if (n == 1)
{
printf("%c-->%c\n", a, c);
count++;
}
else
{
Hant(n - 1, a, c, b);
printf("%c-->%c\n", a, b);
count++;
Hant(n - 1, b, a, c);
}
}
int main()
{
int n = 0;
scanf_s("%d", &n);
Hant(n, 'A', 'B', 'C' );
printf("%d", count);
return 0;
这两个问题也都是使用递归解决的。