一、函数递归
1.递归是什么
递归就是函数自己调用自己
#include <stdio.h>
int main()
{
printf(" hehe\n ");
main();//这就是函数递归
return 0;
}
2.递归的思想
把一个大型复杂的问题层层转化为与原问题相似,但规模比较小的问题求解;直到直到子问题不能再拆分,递归结束
3.书写递归的条件
• 书写递归条件,当满⾜这个限制条件的时候,递归便不再继续
• 每次递归调⽤之后越来越接近这个限制条件
二、函数递归举例
1.求n的阶乘
(1)题目
•题⽬:计算n的阶乘(不考虑溢出),n的 阶乘就是1~n的数字累积相乘
(2)分析
•n的阶乘的公式: n! = n ∗ (n − 1)!
•n的阶乘和n-1的阶乘是相似的问题,但是规模要少了n
n!= n*(n-1)*...*2*1
(n-1)!= (n-2)*(n-3)*...*2*1
5!= 5*4*3*2*1
4!= 4*3*2*1
3!= 3*2*1
2!= 2*1
1!= 1
•有⼀种有特殊情况是:当 n==0 的时候,n的阶乘是1
所以我们可以得出这个方程

(3)解法
递归解法
#include <stdio.h>
int Fact(int n)
{
if (n == 0 )//限制条件
{
return 1;
}
else
{
return n * Fact(n - 1);
}
}
int main()
{
int n = 0;
scanf("%d", &n);
int r = Fact(n);
printf("%d",r);
return 0;
}
常规解法
#include <stdio.h>
int main()
{
int n = 0;
int i = 0;
int sum = 1;
scanf("%d", &n);
for (i = 1; i <= n; i++)
{
sum *= i;
}
printf("%d", sum);
return 0;
}
2.顺序打印每个整形的每一位
(1)题目
输⼊⼀个整数m,按照顺序打印整数的每⼀位。
⽐如:
输⼊:1234 输出:1 2 3 4
输⼊:520 输出:5 2 0
(2)分析
n如果大于9,就需要拆分。
例如:1234%10得到4,/10得到123。以此类推,不断地进行%10 /10的操作,就可以得到1234的每一位。但是有一个问题得到的数字是倒着打印的。我们可以发现其实⼀个数字的最低位是最容易得到的,通过%10就能得到。
Print(n)
如果n是1234,那表⽰为
Print(1234) //打印1234的每⼀位
其中1234中的4可以通过%10得到,那么
Print(1234)就可以拆分为两步:
1. Print(1234/10) //打印123的每⼀位
2. printf(1234%10) //打印4
完成上述2步,那就完成了1234每⼀位的打印
那么Print(123)⼜可以拆分为Print(123/10) + printf(123%10)
以此类推,就可以得到
Print(1234)
==>Print(123) + printf(4)
==>Print(12) + printf(3)
==>Print(1) + printf(2)
==>printf(1)
(3)解法
void Print(int n)
{
if(n>9)
{
Print(n/10);
}
Print("%d", n%10);
}
int mian()
{
int n = 0;
scanf("%d", &n);
Printf(n);
return 0;
}
三、递归与迭代
在C语⾔中每⼀次函数调⽤,都需要为本次函数调⽤在内存的栈区,申请⼀块内存空间来保存函数调⽤期间的各种局部变量的值,这块空间被称为运⾏时堆栈,或者函数栈帧。函数不返回,函数对应的栈帧空间就⼀直占⽤,所以如果函数调⽤中存在递归调⽤的话,每⼀次递归函数调⽤都会开辟属于⾃⼰的栈帧空间,直到函数递归不再继续,开始回归,才逐层释放栈帧空间。所以如果采⽤函数递归的⽅式完成代码,递归层次太深,就会浪费太多的栈帧空间,也可能引起栈溢出(stack overflow)的问题。
所以如果不想使用递归,我们就得想别的办法,通常情况下我们会使用迭代的方式**(迭代通常就是循环)**
例如例题求n的阶乘
我们的常规解法便是迭代解法
#include <stdio.h>
int main()
{
int n = 0;
int i = 0;
int sum = 1;
scanf("%d", &n);
for (i = 1; i <= n; i++)
{
sum *= i;
}
printf("%d", sum);
return 0;
}
611

被折叠的 条评论
为什么被折叠?



