函数递归
什么是递归?
递归就是函数自己调用自己
递归一定是基于函数的
在任何一次函数调用中,都会申请资源,申请的是内存中栈区的资源
栈区的资源是有限的,因此函数不能无限次的递归
递归的思想
把一个大型复杂问题层层转化为一个与原问题相似,但规模较小的子问题来求解,直到子问题不能再被拆分,递归就结束了
所以递归的思考方式就是把大事化小的过程
递归中的递就是递推的意思,归就是回归的意思
递归的限制条件
递归有2个必要条件:
- 递归存在限制条件,当满足这个限制条件的时候,递归便不再继续
- 每次递归调用之后越来越接近这个限制条件
例1:写一个函数fac,用递归实现非负整数n的阶乘
分析:
5!=1* 2* 3* 4* 5 = 4!* 5
4!=1* 2* 3* 4 = 3!* 4
3!=1* 2* 3 = 2!* 3
2!=1*2 = 1!*2
1!=1
0!=1
得出
n ! = (n-1) ! * n
即
fac(n)= fac (n-1)* n ,n>=1时
1 ,n=0时
代码如下:
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int fac(int n) {
if (n == 0)
return 1;
else
return n * fac(n - 1);
}
int main(){
int n;
scanf("%d", &n);
int r = fac(n);
printf("%d\n", r);
return 0;
}
例2:顺序打印一个整数的每一位
思路:
1234%10=4 , 1234/10=123
123%10=3 , 123/10=12
12%10=2 , 12/10=1
1%10=0 ,1/10=0
用递推实现:
Print(1234)
Print(123) 4
Print(12) 3 , 4Print(1) 2, 3 , 4
即
n是一位数的时候
n<=9 ,printf(“%d”,n)
n如果不是一位数
Print(n/10)+printf(“%d”,n%10)
代码如下:
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
void Print(int n) {
if (n > 9) {
Print(n / 10);
}
printf("%d ", n % 10);
}
int main(){
int n;
scanf("%d", &n);
Print(n);//将n的每一位按顺序打印在屏幕上
return 0;
}
递归与迭代
在C语言中每一次函数调用,都需要为本次函数调用在内存的栈区,申请一块内存空间来保存函数调用期间的各种局部变量的值,这块空间被称为运行时堆栈,或者函数栈帧
函数不返回,函数对应的栈帧空间就一直占用,所以如果函数调用中存在递归调用的话,每一次递归函数调用都会开辟属于自己的栈帧空间,直到函数递归不再继续,开始回归,才逐层释放栈帧空间
所以如果采用函数递归的方式完成代码,递归层次太深,就会浪费太多的栈帧空间,也可能导致栈溢出
不使用递归,可以用迭代的方式(通常就是循环的方式
例1:
计算 n的阶乘
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int fac(int n) {
int i = 0;
int ret = 1;
for (i = 1;i < -n;i++) {
ret *= i;
}
return ret;
}
int main() {
int n;
scanf("%d", &n);
int r = fac(n);
printf("%d\n", r);
return 0;
}
例2:
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int main(){
int n;
scanf("%d", &n);
while (n) {
printf("%d ", n%10);
n /= 10;
}
;
return 0;
}
一个问题比较复杂,不容易写出非递归(迭代)的代码,但是递归的方式很容易写出来,那么这个时候,如果递归没有明显缺陷,就用递归解决
例3:斐波那契数列
Fib(n)=
n<=2时 ,1
n>2时 ,Fib(n-1)+Fib(n-2)
用递归实现:
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int Fib(int n) {
if (n <= 2)
return 1;
else
return Fib(n - 1) + Fib(n - 2);
}
int main() {
int n;
scanf("%d", &n);
int r = Fib(n);
printf("%d\n", r);
return 0;
}
会进行大量的重复计算
所以用递推来解决:
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int Fib(int n) {
int a = 1;
int b = 1;
int c = 1;
while (n>=3) {
c = a + b;
a = b;
b = c;
n--;
}
return c;
}
int main() {
int n;
scanf("%d", &n);
int r = Fib(n);
printf("%d\n", r);
return 0;
}
END…
愿所有角色丰盈你,却不替代你;
愿所有故事经过你,却不写目的地。