文章目录
前言
本文总结于此文章
一、函数递归
什么是递归
例如(史上最简单的递归):
#include<stdio.h>
int main()
{
printf("Hello World\n");
main();
}
先一直打印 Hallo World,最终程序挂掉
递归的两个重要条件
练习一
我们的第一想法就是:
1234%10 = 4
1234/10=123
123%10=3
123/10=12
12%10=2
12/10=1
1%10=1
1/10=0
这样我们能得到数字的每一位,然后我们把他们打印出来
#include<stdio.h>
#define _CRT_SECURE_NO_WARNINGS
int main()
{
int a ,n;
printf("请输入一个无符号的整型:");
scanf("%d", &a);
while(a>10)
{
if(a>10)
{
n = a % 10;
printf("\n%d ",n);
a = a / 10;
}
}
printf("\n%d",a);
return 0;
}
我们发现输出结果和题目中的不同,这个问题需要我们用递归来进行
因为递归的原理是先递推再回归,一层一层的传递下去
我们定一个print函数,它的功能是按照顺序打印num的每一位。
在写代码的过程中,我们只需要关注最后一层的递推和回归
我们的想法就是先把余的1打印出来,再把上一层余的2打出来,以此类推。
printf("%d ",n%10);
因为这是我们上一层所调用的print函数,当这个函数执行完后,我们还要回到上一层,继续执行代码
printf("%d ",n%10);
依次循环,这就是我们的递归
首先,我们先把递归函数写出来
void print(int n)
{
if(n<10)
{
printf("%d ",n);
}
else
{
print(n/10);
printf("%d ",n%10);
}
}
代码实现:
#include <stdio.h>
void print(int n)
{
if(n<10)
{
printf("%d ",n);
}
else
{
print(n/10);
printf("%d ",n%10);
}
}
int main ()
{
int a=0;
printf("输入一个数字\n");
scanf("%d",&a);
print(a);
return 0;
}
当然也可以更简便:
其更简便的最根本的原因是限制条件不同,使用n>9时,就不用使用else
#include<stdio.h>
void print(unsigned int n)
{
if (n > 9)限制条件
{
print(n / 10);每次递归调用之后越来越接近这个限制条件
}
printf("%d ", n % 10);
}
int main()
{
unsigned int num = 0;
scanf("%u", &num);
print(num);
return 0;
}
练习二
写一个可以求字符串长度的代码(老朋友了已经是)
我们有一个专门求字符串长度的库函数 strlen
长度等于开始到空字符之间的字符数(不包括空字符本身)\0
首先我们先创建一个字符数组
char arr[] = "abc";
再用strlen函数
#include<stdio.h>
#include<string.h>
int main()
{
char arr[] = "abc";
strlen(arr);
printf("%d", strlen(arr));
return 0;
}
我们自己创建一个函数,模仿写一个strlen函数
这里先用非递归方式
#include<stdio.h>
#define _CRT_SECURE_NO_WARNINGS
int my_strlen(char* str)
{
int count = 0;
while (*str != '\0')
{
count++;
str++;
}
return count;
}
int main(){
char i[100];
printf("请输入一个字符串: ");
scanf("%s", i);
my_strlen(i);
printf(" %d", my_strlen(i));
return 0;
}
count在这里只是起到一个计数器的作用
下来试一下递归
如果第一个字符不是\0,那说明字符串里至少有一个字符
这就是我们的思路
首先写递归函数:
int my_strlen(char* str)
{
if(*str !='\0')
{
return 1 + my_strlen(str+1);
}
else
{
return 0;
}
}
递归过程如下
代码如下
递归与迭代
练习三
先构思好递归(思路如下,是别的博主的图,博主文章在前言)
代码实现
#include<stdio.h>
#define _CRT_SECURE_NO_WARNINGS
int my(int i)
{
if(i<=1)
{
return 1;
}
else
{
return i *my(i -1);
}
}
int main(){
int i;
printf("请输入一个数字: ");
scanf("%d", &i);
my(i);
printf("%d", my(i));
return 0;
}
递归函数也只是一种解决问题的技巧,它和其它技巧一样,也存在某些缺陷,具体来说就是:递归函数的时间开销和内存开销都非常大,极端情况下会导致程序崩溃。
所以这道题最好用非递归的方式来计算,比如迭代,循环是一种迭代
练习四
什么是斐波那契数列
流程如下:
写出代码:
#include<stdio.h>
#define _CRT_SECURE_NO_WARNINGS
int Fib(int n)
{
if(n<=2)
{
return 1;
}
else
{
return Fib(n-1)+Fib(n-2);
}
}
int main()
{
int n = 0;
scanf("%d",&n);
printf("%d",Fib(n));
return 0;
}
在练习三、四中出现的问题
我们会出现这样的问题
原因是因
函数在调用过程中很多计算,其实一直在重复
系统分配给程序的栈空间是有限的,但是如果出现了死循环,或者(死递归),这样有可能导致一直开辟栈空间,最终产生栈空间耗尽的情况,这样的现象我们称为栈溢出
如何解决这个问题
原文链接:https://blog.csdn.net/m0_68468727/article/details/126466506
#include<stdio.h>
int Fib(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 = 0;
scanf("%d", &n);
printf("%d\n", Fib(n));
return 0;
}
提示