6.0、C语言——递归函数
函数递归
什么是递归?
程序调用自身的编程技巧称为递归(recursion),递归作为一种算法在程序设计语言中广泛应用。一个过程或函数在其定义或说明中有直接或简介调用自身的一种方法,他通常把一个大型复杂的问题层层转化为一个与原问题相似的规模较小的问题来求解,递归策略只需要少量的程序就可描述出解题过程所需要多次重复的计算,大大减少了程序的代码量。递归的主要思考方式在于:把大事化小
递归的两个必要条件
存在限制条件,当满足这个限制条件的时候,递归便不再继续
每次递归调用之后越来越接近这个限制条件
什么是栈溢出:
首先来看一下 每块内存区域存放的数据类型
写一个最简单的递归调用:
#include <stdid.h>
int main() {
printf("递归调用main()函数");
main();
return 0;
}
调用函数的时候会向栈区申请分配一块空间,那么像上面这个代码,每次调用函数都会申请一块空间,然后他又在不断的自己调用自己,最后导致栈空间被占满造成 栈溢出 的情况发生 stack overflow
给大家介绍一个程序猿的知乎网站 stackoverflow:
Stack Overflow - Where Developers Learn, Share, & Build Careers
练习1:利用递归函数将一个十进制数的每一位依次打印出来,例如1234 ,打印1 2 3 4
#include <stdio.h>
void print(int num) {
if(num < 9) {
print(num/10);
}
printf(num % 10);
}
int main() {
print(1234);
return 0;
}
练习2:在不创建临时变量的情况下,写一个可以计算字符串长度的函数
#include <stdio.h>
int my_strlen(char* arr) {
if(*arr != '\0'){
return 1 + my_strlen(arr + 1);
}else {
return 0;
}
}
int main() {
char arr[] = "abcdefg";
int len = my_strlen(arr);
printf("my_strlen = %d", len);
return 0;
}
练习3:利用递归计算一个数的阶乘
#include <stdio.h>
int fac(int num) {
if(num > 1) {
return num*fac(num - 1);
}else {
return 1;
}
}
int main () {
int result = fac(9);
printf("result = %d", result);
return 0;
}
练习4:利用递归算出给定位置的斐波那契数【斐波那契数就是前两个数相加等于后一个数,1,1,2,3,5,8,13,21......】
int fib(int num) {
if(num <= 2) {
return 1;
}else {
return fib(num-1)+fib(num-2)
}
}
int main() {
int num = 0;
scanf("%d", &num);
int result = fib(num);
printf("%d", result);
}
这个函数执行的时候我们可以发现,当我们输入的数字较小的时候也就是所求的斐波那契数位置靠前的时候结果很快就计算出来了,但是当我们输入50的时候发现结果却迟迟没有计算出来~这是为什么呢?
我们在上述代码中加入以下代码来测试一下,看看第4个斐波那契数会计算多少次?
int count = 0;
int fib(int num) {
if(num == 3) {
count++;
}
if(num <= 2) {
return 1;
}else {
return fib(num-1)+fib(num-2)
}
}
int main() {
int num = 0;
scanf("%d", &num);
int result = fib(num);
printf("result = %d", result);
printf("count = %d",count);
}
那么计算出来count的结果是三千多万次,很恐怖这个次数。所以当我们遇到计算菲波那切数的时候就不太适合用递归去计算了
那这时就应该用循环迭代的方式去完成这个函数:
#include <stdio.h>
int fib(int num) {
int a = 1;
int b = 1;
int c = 1;
int count = 0;
while(count < num - 2) {
c = a + b;
a = b;
b = c;
count++;
}
return c;
}
int main() {
int n = 2;
int result = fib(n);
printf("result = %d",result);
return 0;
}
计算结果的速度明显比较递归来说,快了不要太多~