网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
return z;
}
## 函数递归
### 1、什么是递归
程序调用自身的编程技巧称为递归( recursion)—— 自己调用自己
递归做为一种算法在程序设计语言中广泛应用。
一个过程或函数在其定义或说明中有直接或间接调用自身的一种方法,它通常把一个大型复杂的问题层层转化为一个与原问题相似的规模较小的问题来求解
递归策略——只需少量的程序就可描述出解题过程所需要的多次重复计算,大大地减少了程序的代码量。
递归的主要思考方式在于:把大事化小
### 2、递归的两个必要条件
(1)存在限制条件,当满足这个限制条件的时候,递归便不再继续。
(2)每次递归调用之后越来越接近这个限制条件。
#### 举例1:
接受一个整型值(无符号),按照顺序打印它的每一位。
例如: 输入:1234
输出 1 2 3 4
**分析:**
递归解决:大事化小 —— 函数自己调用自己
函数的形式:
Print(1234)—— Pirnt(123)+ 4 —— Print(12)+ 3 + 4 —— Print(1) + 2 + 3 + 4
#include<stdio.h>
void Print(int num)
{
if (num > 9)
Print(num/10); //自己调用自己
printf("%d ", num % 10);
}
int main()
{
int num = 1234;
Print(num); //自己定义的打印函数
return 0;
}
**画图讲解:** ![](https://img-blog.csdnimg.cn/20210823215426411.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L0lUX0luZmVjdG9y,size_16,color_FFFFFF,t_70)
**一种常见的递归错误分析:**
#include<stdio.h>
void Print(int num)
{
//if (num > 9)
Print(num / 10);
printf("%d ", num % 10);
}
int main()
{
int num = 1234;
Print(num); //自己定义的打印函数
return 0;
}
这时就会无限的递归下去——形成死递归——出现栈溢出的现象。
每一次函数的创建都要为函数申请空间。
![](https://img-blog.csdnimg.cn/20210823230128198.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L0lUX0luZmVjdG9y,size_16,color_FFFFFF,t_70)
#### 举例2
题目:不利用库函数,求字符串的长度
**一般方法:**
//用函数求字符串长度
#include<stdio.h>
int my_strlen(char* arr) //传的是字符地址要用字符指针变量来接收
{
int count = 0;
while (*arr != ‘\0’)
{
count++;
arr++;
}
return count;
}
int main()
{
char arr[10] = “abcd”;
//其中的arr是数组名,也是首元素的地址
int ret = my_strlen(arr); //自己定义的一个求字符长度的函数
printf(“%d\n”, ret);
return 0;
}
补充:
如果是:字符指针变量 —— char\* p —— p+1 —— 跳过一个字符
如果是:整型指针变量 —— int\* p —— p+1 —— 跳过四个字符
**利用递归的方法:**
分析:
函数形式:my\_strlen(abcd) —— 1 + my\_strlen(bcd) —— 1 + 1 + my\_strlen(cd) ——
1 + 1 + 1 + my\_strlen(d) —— 1 + 1 + 1 + 1 + 0
代码展示:
//用函数求字符串长度
#include<stdio.h>
int my_strlen(char* arr)
{
if (*arr == ‘\0’)
return 0;
else
{
return 1 + my_strlen(arr + 1);
}
}
int main()
{
char arr[10] = “abcd”;
int ret = my_strlen(arr);
printf(“%d\n”, ret);
return 0;
}
#### 举例3:
求n的阶乘。(不考虑溢出)
**一般求解:**
#include<stdio.h>
int Fac(int n)
{
int tem = 1;
while (n > 0)
{
tem *= n;
n–;
}
return tem;
}
int main()
{
int n = 0;
scanf(“%d”, &n);
int ret = Fac(n);
printf(“%d\n”, ret);
return 0;
}
**递归求解:**
#include<stdio.h>
int Fac(int n)
{
if (n <= 1)
{
return 1;
}
else
{
return n * Fac(n - 1);
}
}
int main()
{
int n = 0;
scanf(“%d”, &n);
int ret = Fac(n);
printf(“%d\n”, ret);
return 0;
}
#### 举例4:
求第n个斐波那契数。(不考虑溢出)
什么是斐波那契数:1 1 2 3 5 8 13 21 34 55 ...........
**递归求解:**
//求第n个斐波那契数。(不考虑溢出)
#include<stdio.h>
int Fan(int n)
{
if (n <= 2)
return 1;
else
return Fan(n - 1) + Fan(n - 2);
}
int main()
{
int n = 0;
scanf(“%d”, &n);
int ret = Fan(n);
printf(“%d\n”, ret);
return 0;
}
这个递归函数只能求比较小的数字,如果求比较大的数字就会计算的很慢
int count = 0; //全局变量
int Fan(int n)
{
if(n == 3)
count++;
if (n <= 2)
return 1;
else
return Fan(n - 1) + Fan(n - 2);
}
如果上面这个函数求第40位的斐波那契数:count 就会是一个非常大的数字。
分析:
![img](https://img-blog.csdnimg.cn/img_convert/39a67db8caaea41feb70963cdd1f9074.png)
![img](https://img-blog.csdnimg.cn/img_convert/a1e7b8f0da03515fce29b6c2c5d3a3dc.png)
**既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上C C++开发知识点,真正体系化!**
**由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新**
**[如果你需要这些资料,可以戳这里获取](https://bbs.csdn.net/topics/618668825)**
契数:count 就会是一个非常大的数字。
分析:
[外链图片转存中...(img-41m35vda-1715889358779)]
[外链图片转存中...(img-Kc8dcOX9-1715889358779)]
**既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上C C++开发知识点,真正体系化!**
**由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新**
**[如果你需要这些资料,可以戳这里获取](https://bbs.csdn.net/topics/618668825)**