在c语言中如何使用递归函数(C语言学习篇27)
在c语言中如何使用递归函数(C语言学习篇27)
引言
前面我们讲了函数的组成部分以及传参详解,函数指针等知识,对函数相关知道有了一定了解,已经足够应对平时的开发和学习了。今天我们再来说说一个比较特殊的函数,就是我们的今天的主题——递归函数,为什么说是特殊呢,这是因为平时我们写的函数都是通过别人或者说是其他代码来调用的,而递归函数是自己来调用自己, 是不是觉得很特别呢?递归函数也是常常在笔试题中出现的哦~
计算阶乘
递归函数本质也是函数,只是函数的特殊性,应用在某些特殊的场景,以下我们介绍几种递归函数的应用场景,来感受下其美丽吧。以下是计算数字5阶乘,具体代码如下所示:
#include
分析:
1.首先我们定义了一个递归函数int cal_factorial(int n),传入参数n是指要计算阶乘的数,返回值为最终计算阶乘的结果。
2.在cal_factorial函数内部,首先判断传入的参数sizh是否符合规范,比如要计算的阶乘,那么必须是一个大于等于1的正整数。
3. 重点:接着if(n == 1)作为递归退出条件,因为我们知道当计算到乘以1时,说明已经完成了阶乘的计算(所谓的阶乘是指一个数n,一直乘以不断减1的数,直到乘以1为止:n*(n-1)*(n-2)....*1),而这里的return 1,是返回1本身,并与之前递归的结果(result=n*(n-1)*(n-2)....*2) 相乘(*1),得到完成的计算阶乘的式子。否则(else),返回 (n*cal_factorial(n-1)); 这里就用到递归, 这里我们以计算5阶乘为例子,那么第一调用该递归函数时,就会进到else语句部分中,即执行 5*cal_factorial(5-1),而这里的cal_factorial(5-1), 还是会进到else部分中,即变成了 5 * 4 * cal_factorial(4-1), 同理再次进入else部分,变成5*4*3*cal_factorial(3-1),接着还是同理变成5*4*3*2*cal_factorial(2-1),到了这里cal_factorial中传入参数等于1,再次调用递归函数时,就会进入if(n==1)语句部分,直接返回1,退出递归,此时结果就成了5*4*3*2*1。
4. 然后我们在主函数中定义一个int变量res来接收递归函数cal_factorial返回值,并通过printf打印
编译运行结果:
使用递归函数的条件
首先要说明的是并不是所有的问题都能用递归解决,要使用递归函数的就必须具备以下2个条件:
要有递归的方式
递归的思想是指: 为了解决当前问题 F(n),就需要解决问题 F(n–1),而 F(n–1) 的解决依赖于 F(n–2) 的解决……就这样逐层分解,分解成很多相似的小事件,当最小的事件解决完之后,就能解决高层次的事件。这种“逐层分解,逐层合并”的方式就构成了递归的思想。
要有终止条件
每当进行一次递归,我们都需要判断条件是否满足,继续递归还是退出。如果没有递归终止条件或者这个条件不能被满足,则这个递归就没有收敛性,而没有收敛性是一个非常可怕的事情,因为函数递归占用的是栈内存,每次递归调用都会消耗一些栈内存,因此必须在栈内存耗尽之前就要完成递归收敛,否则就会出现栈溢出,严重时就会宕机。
#include
在上面我们定义了递归函数digui,并且没有做递归退出处理(digui(n)),导致一直递归下去,同时我们每次递归都定义1000个大小int类型的数组,用来撑爆栈内存。我们看看编译运行的结果:
递归函数的执行顺序
递归函数的执行和返回就类似剥洋葱一般,首先一层一层的往里剥,剥到最深处后,再一层一层往外褪去,我们可以通过以下例子来感受下:
#include
说明:
1.首先我们定义一个递归函数void digui(int n), 判断n大于1时(if(n>1)),进入函数都打印递归的值
2. 当n=1时,进入else语句部分,打印结束递归,和n的值,这里n的值肯定为1哦
3. 接着我们打印递归后的n的值
4. 在主函数中我们向递归函数传入3,用来依次打印递归前后值的变化
我们先编译运行,看看结果:
从结果我们可以看出,一进入递归函数,就会打印递归前的值(当前n的值), 然后一直执行if(n > 1)语句中的递归函数,直到n=1;递归函数才运行到printf("结束递归. n = %d.\n", n );(这里大家可以看到在此之前一直都没有执行printf("递归后:n = %d.\n", n))退出了if(n > 1)重复递归, 然后依次打印了3此递归后的值, 并且可以看到值是1, 2, 3。 这是理解递归执行顺序的重点: 首先打印的是1,而不是3, 这里是因为在之前一直递归到n=1(剥洋葱剥到最深处了),然后依次退出来, 顺序就是1,2,3。大家好好感受下其中的妙处。这是真正理解递归函数的重点,一定要掌握!
总结
递归的主要目的是为了简化程序设计,使结构简洁清晰,可读性强。 在数学方面应用的颇多,如典型的计算阶乘,求斐波那契数列等。但是递归的缺点也是很明显的,比如速度慢,运行效率低,对栈空间占用多,大量的函数调用,特别占用cpu,每次函数调用都需要保存上下文,因此大家在使用递归函数的时候需要慎重小心。
,
-
- 武魂玄冰选什么血统(武魂玄冰冰霜系攻略)
-
2023-08-23 21:39:01
-
- 嘉庆的儿子有几人(嘉庆有九个女儿)
-
2023-08-23 21:36:38
-
- oppo平台游戏中心8.6.0(OPPO游戏中心8.0焕然一新)
-
2023-08-23 21:34:15
-
- 震网病毒的影响(及其他高危漏洞)
-
2023-08-23 21:31:53
-
- 14个迹象提醒身体该动了(出现5个信号暗示身体该)
-
2023-08-23 21:29:30
-
- 小白与红花会的关系(小白宣布退出红花会)
-
2023-08-23 21:27:08
-
- 我最喜欢的25首主题曲(那些记忆中好听的主题曲)
-
2023-08-23 21:24:45
-
- 钳形表详解(数字钳形表测量使用方法图解)
-
2023-08-23 21:22:22
-
- 麻雀课文作者屠格涅夫(麻雀作者王希杰)
-
2023-08-23 21:20:00
-
- 澳洲森林大火人们看到考拉的泪奔(澳大利亚下黑雨)
-
2023-08-23 21:17:37
-
- 山口百惠和三浦友和是真的夫妻吗(还能相信爱情吗)
-
2023-08-23 21:15:14
-
- 飞夺泸定桥在哪个省(红军飞夺泸定桥)
-
2023-08-23 21:12:52
-
- twins资料(YY烧1亿打造内地版Twins)
-
2023-08-23 21:10:29
-
- 速冻包子生坯冷冻时要封保鲜膜吗(速冻生包子保质期是多久)
-
2023-08-23 21:08:07
-
- thinkbook16+32g测评(性能小钢炮ThinkBook)
-
2023-08-23 21:05:44
-
- 普联16口以太网交换机(2GSFP机架式千兆2光16电网管型POE工业以太网交换机
-
2023-08-23 21:03:21
-
- 老粗布传统制作工艺(老布新做她把小小的粗布打造成非遗文化特色产业)
-
2023-08-23 21:00:59
-
- 北宋命运悲惨的帝姬(北宋最美的公主)
-
2023-08-23 20:58:36
-
- 营养美味的排骨汤家常必备哦(9种排骨汤的做法)
-
2023-08-23 20:56:14
-
- 盐碱地治理新思路(盐碱地改良治理新方法)
-
2023-08-23 20:53:51