当前位置:网站首页>6.函数的递归
6.函数的递归
2022-07-06 09:19:00 【是王久久阿】
目录
示例1:创建my_strlen函数,模拟实现strlen功能。
1.什么是递归?
程序调用自身的编程技巧称为递归( recursion)。
递归做为一种算法在程序设计语言中广泛应用。 一个过程或函数在其定义或说明中有直接或间接调用自身的一种方法,它通常把一个大型复杂的问题层层转化为一个与原问题相似的规模较小的问题来求解。
递归策略只需少量的程序就可描述出解题过程所需要的多次重复计算,大大地减少了程序的代码量。
递归的主要思考方式在于:把大事化小
2.递归的必要条件
1、递归必须满足限制条件,当满足这个条件时,递归停止。
2、每一次递归后都必须接近限制条件。
递归的使用必须同时满足以上的两个条件,当其中之一不满足时,函数将陷入死递归。
3.具体示例讲解
示例1:创建my_strlen函数,模拟实现strlen功能。
迭代方法
核心思想:
- strlen是用来求字符串长度的,其结果不包含终止符'\0'。例如:用strlen求字符串“abcdef”的长度为6。(strlen的返回值是无符号整型,这里我们模拟的函数返回类型为整型即可)
- 因为strlen的结果不包含终止符'\0',所以我们可以把\0作为终止条件:从第一个字符开始读取,如果该位置不是\0,迭代继续,直到读取到\0时,停止读取。
普通方法(创建2个临时变量)
#include<stdio.h>
int my_strlen(char ch[])//[]里写不写数字都一样
{
int count = 0;//计数
int i = 0;//每次迭代后位置往后挪一个字符
while (ch[i] != '\0')
{
count++;
i++;
}
return count;
}
int main()
{
char ch[] = "abcdef";
int num = my_strlen(ch);
printf("%d\n", num);
return 0;
}
指针方法(创建1个临时变量)
如果对指针有所了解的同学,也可以使用指针,更加方便。
#include<stdio.h>
int my_strlen(char* ch)
{
int count = 0;
while (*(ch++) != '\0')//*ch为解引用
{
count++;
}
return count;
}
int main()
{
char ch[] = "abcdef";
int num = my_strlen(ch);
printf("%d\n", num);
return 0;
}
通过迭代可以顺利的实现strlen的功能,但是无论是普通的方法还是利用指针的方法,我们都创建了临时变量count用来计数,假设不使用临时变量呢?又如何进行?
递归方法
核心思想:
- 递归的利用函数自己调用自己,以此来将一些复杂的事情简单化。
- 设置my_strlen函数模拟实现,假设求字符串“abcedf”的长度,我们可以把字符串“abcdef”拆分成1+字符串“bcdef”,求字符串“abcedf”就变成了求1+"bcdef"的问题了,求"bcdef"的长度又可以调用我们设置的my_strlen函数。
- 然后再将“bcdef”拆分成1+字符串“cdef”......直到剩最后一个字符‘f’时,把f拆分成1+‘\0’,当读取到‘\0’时,停止调用my_strlen函数,递归结束。
递:递归中首先要递,我们将字符串一直拆分直到拆到\0这个动作就是递。
归:递归中递完了才能归,当函数达到限制条件,无法再调用函数时,将本次函数的结果作为返回值,返回到上一个函数中,直到返回到第一次调用函数时。
递归中的递和归是相对应的,递和归的次数是一致的,比如某函数递归了6次,那么必定执行了6次递,6次归。
#include<stdio.h>
int my_strlen(char* ch)
{
if (*ch != 0)
return 1 + my_strlen(ch+1);
else
return 0;
}
int main()
{
char ch[] = "abcdef";
int num = my_strlen(ch);
printf("%d\n", num);
return 0;
}
上述代码中,ch为字符串首地址元素,*ch为对ch存储的地址进行解引用,通过该地址找到字符串中的元素。
每次递归时地址向后+1,因为用char*的指针类型接收的ch的地址,所以这里+1表示为向后一个字节,如果是int*的指针类型,+1则是每次向后4个字节。(这里不要使用++ch,会彻底改变ch)。
当读到'\0'时,停止递归。
示例2:求斐波那契数
斐波那契数:1、1、2、3、5、8、13、21、34、56......从第三项开始,每一项的值等于前两项的和。
核心思想:
- 当n=5时,第5个斐波那契数=第四个斐波那契数(n-1)+第三个斐波那契数(n-2)
- 第四个斐波那契数=第三个斐波那契数(n-2)+第二个斐波那契数(n-3)
- 第三个斐波那契数=第二个斐波那契数1+第一个斐波那契数1
这样就把求第五个斐波那契数,转换成了求n个第二个斐波那契数和求m个第一个斐波那契数的问题了。
#include<stdio.h>
int fibo(int n)
{
if (n > 2)
return fibo(n - 1) + fibo(n - 2);
else
return 1;
}
int main()
{
int n = 0;
scanf("%d", &n);
printf("%d\n", fibo(n));
return 0;
}
示例3:求水仙花数
求所有的水仙花数,水仙花数是一个三位数,各位数字的立方和等于其本身。
例如:,故153是水仙花数。
核心思想:
例如:求125各位的立方
- 首先,125可以拆分为12和5,求5的立方+求12各位的立方
- 其次,12可以拆分为2和5,求2的立方+求1的各位的立方
- 最后,1就它自己,求1的立方。
如何将125拆分成12和5呢?
这里将125/10,整数相除取商12;将125%10,取余数5。
#include<stdio.h>
#include<math.h>
int flo(int i)
{
int sum = 0;
if (i / 10 != 0)
{
sum = flo(i / 10);
}
return sum += pow((i % 10), 3);
}
int main()
{
int i = 0;
for (i = 100; i < 1000; i++)
{
if (flo(i) == i)
{
printf("%d是水仙花数\n", i);
}
}
return 0;
}
return sum += pow((i % 10), 3);可以理解为:
1、sum += pow((i % 10), 3);
2、return sum;
当1/10=0时,表达式为假,便不再调用函数,开始进行下一条语句,计算sum的值,然后return到上一个递归中,直到全部return完,递归结束。
4.递归与迭代
递归与迭代的区别
在上述计算斐波那契数时,如果求第35个斐波那契数,程序很快便会给出结果;但是如果求第50个斐波那契数,程序则会运行的非常缓慢。
这是因为在求斐波那契数时,我们把所有的问题都转换成了求n个第一个斐波那契数和第m个斐波那契数。
仅仅是求第五个斐波那契数,便调用了9次函数自身。假如求第40个斐波那契数呢?会调用多少次函数?
这里设置一个全局变量count,对函数的调用次数进行计数。
int count = 0;
#include<stdio.h>
int fibo(int n)
{
count++;
if (n > 2)
return fibo(n - 1) + fibo(n - 2);
else
return 1;
}
求第40个斐波那契数共调用了2亿多次函数,每一次调用函数都需要在栈区中开辟一块空间,然而栈区的空间是有限的,当栈区满后,程序便进行不下去了。
当发生以上这种情况时,往往使用迭代效率会更加高,或者用static对象代替局部变量对象,以此释放栈区中的空间。
方式 | 优点 | 缺点 |
递归 | 形式清晰,思路明确 | 运行速度慢,栈区容易溢出 |
迭代 | 效率更高,速度更快 | 代码可读性差 |
用迭代的方式求斐波那契数
核心思想:
- 通过创建临时变量的方式,存储前两项相加的结果,并且作为下一次迭代时的被加项目。
- 为了防止数据溢出,这里用unsigned long long 来存储我们的结果。
#include<stdio.h>
unsigned long long fibo(int n)
{
unsigned long long sum=0;
unsigned long long St=0;
unsigned long long Sec=0;
sum = Sec = 1;
while (n > 2)
{
n -=1;
St = Sec;
Sec = sum;
sum = St + Sec;
}
return sum;
}
int main()
{
int n = 0;
scanf("%d", &n);
printf("第%d个斐波那契数是%llu\n",n,fibo(n));
return 0;
}
第50个斐波那契数是12586269025,将近126亿。
第100个斐波那契数是3736710778780434371,373京左右,unsigned long long存储的最大值为18446744073709551615,不过是1844京左右。然而这么大的数也只是迭代了98次得到的结果。
“不积跬步,无以至千里;不积小流,无以成江海。骐骥一跃,不能十步;驽马十驾,功在不舍。锲而舍之,朽木不折;锲而不舍,金石可镂。”C语言的学习也是如此,每天进步一点,今天比昨日博学一点,明日又比今天多学一分,相信我们最终都学有所成,前途无限。
5.递归练习题
这里整理了相关递归练习题,每道题都有详细讲解,有兴趣的同学可以尝试做一下。
并且在扫雷游戏中,相关功能的实现也用到了函数的递归。
边栏推荐
- Dark chain lock (lca+ difference on tree)
- Counter attack of flour dregs: redis series 52 questions, 30000 words + 80 pictures in detail.
- TYUT太原理工大学2022软工导论大题汇总
- Network layer 7 protocol
- 最新坦克大战2022-全程开发笔记-1
- 4.30动态内存分配笔记
- 阿里云微服务(二) 分布式服务配置中心以及Nacos的使用场景及实现介绍
- View UI Plus 发布 1.3.1 版本,增强 TypeScript 使用体验
- Alibaba cloud microservices (IV) service mesh overview and instance istio
- 分支语句和循环语句
猜你喜欢
(super detailed II) detailed visualization of onenet data, how to plot with intercepted data flow
西安电子科技大学22学年上学期《基础实验》试题及答案
Differences and application scenarios between MySQL index clock B-tree, b+tree and hash indexes
(ultra detailed onenet TCP protocol access) arduino+esp8266-01s access to the Internet of things platform, upload real-time data collection /tcp transparent transmission (and how to obtain and write L
Fgui project packaging and Publishing & importing unity & the way to display the UI
Edit distance (multi-source BFS)
What are the advantages of using SQL in Excel VBA
2年经验总结,告诉你如何做好项目管理
西安电子科技大学22学年上学期《信号与系统》试题及答案
9.指针(上)
随机推荐
TYUT太原理工大学2022软工导论大题汇总
One article to get UDP and TCP high-frequency interview questions!
Several high-frequency JVM interview questions
【快趁你舍友打游戏,来看道题吧】
Tyut Taiyuan University of technology 2022 introduction to software engineering
IPv6 experiment
Introduction pointer notes
分支语句和循环语句
Cloud native trend in 2022
Ten minutes to thoroughly master cache breakdown, cache penetration, cache avalanche
系统设计学习(一)Design Pastebin.com (or Bit.ly)
架构师怎样绘制系统架构蓝图?
Application architecture of large live broadcast platform
TYUT太原理工大学2022数据库大题之分解关系模式
Smart classroom solution and mobile teaching concept description
Record: Navicat premium can't connect to MySQL for the first time
2-year experience summary, tell you how to do a good job in project management
List set map queue deque stack
Fundamentals of UD decomposition of KF UD decomposition [1]
阿里云微服务(四) Service Mesh综述以及实例Istio