目录
前言:
这是继上一篇文章心得:实操函数代码的小结的补充,函数的知识点比较多,上次是对实操函数代码的小结,本次是对函数其他的补充。
一.函数的递归
递归这一说法是我浏览优快云有关C语言函数部分相关内容时发现的 ,一开始并不知道,在慢慢探索,自己去手敲函数递归的时候,才对函数递归有了一些理解。
1.递归和函数嵌套的区别
递归的意思时在写一个函数的时候,比如add();,在这个函数下面,自己再去调用本身这个函数,大白话就是自己调用自己,和函数的嵌套调用还是有本质区别的,以图片举例
这是函数的递归,即运行第27行代码时,调用print这个函数,而在第13行~21行中,又再一次调用了它本身,此时不会执行printf命令,只会等它调用到达到限制条件时,函数才return。
而嵌套呢,是在第一个函数的调用的时候,执行到另外一个不是它本身的函数,执行完返回后才回到第一个调用函数。这是两者的区别所在。
2.递归使用的条件
1.限定条件
递归需要有一个限制条件来限定它,不然就会发生死递归,导致栈溢出,因为每一次调用函数,计算机都会给函数开辟一个栈的内存空间,当然内存空间不是无限大的,总会溢出,如果不增加一个限制条件,那么必定会发生错误。如下代码就是会一直走下去,最后卡死
#include <stdio.h>
int main()
{
printf("hehe\n");
main();//main函数中⼜调⽤了main函数
return 0;
}
2.越来越接近限制条件,直到停止递归
这个在敲代码敲多之后会有所体会,就是每一次递归,在有限定条件的前提下,都会越来越接近那个值,就像for循环和while里的判断条件语句一样,达到条件后,就会开始依次往上返回 ,最后产生结果。
二.递归的思想
1.先递
在了解递归使用的条件后,就会产生一个思想,那么递归是怎么走的呢?分两步,递就是递推的意思,归就是回归的意思。在函数中,函数遇到第一个自己,调用自己,判断是否满足条件,满足,再递推调用下一个自己,直到不满足,递部分结束,开始ruturn了。
2.再归
回归,简单说就是哪里来的回哪里去,一般都是调用了自己n次,就返回n-1次,(因为第n次判断条件发现不满足就不再进行调用了,就会执行返回语句)返回到第一次调用这个函数的时候,return结果,回到main主入口,大致就这个意思。自己慢慢敲多了,实操多了就能体会了。
这里演示一个顺序打印数字的代码来观察
演示:
输⼊⼀个整数m,按照顺序打印整数的每⼀位。 ⽐如: 输⼊:1234 输出:1 2 3 4
思路就是把1234%10,得到最低位4,剩下还有123。不妨拆成两部分,一部分直接就是printf(1234%10),另外一个部分为1234/10=123。这里就是利用调用函数进行传递操作
3又可以是123%10的结果,123/10=12。
总结就是
void Print(int n)
{
if(n>9)
{
Print(n/10);
}
printf("%d ", n%10);
}
int main()
{
int m = 0;
scanf("%d", &m);
Print(m);
return 0;
}
当代码走到5行的时候,由于1234>9,123>9....,有限制条件存在,它是不会走到printf那一步进行打印的,会第5行遇到函数,回到第一行,然后又到第5行,反复。。。直到函数Print12/10之后,if(1<9),条件不成立,才会进行归,那么第一个就是1%10=1,第二个12%10=2,第三个123%10=3,第四个为4,依次打印。
其实当我写到这里的时候,我也是在进行一个复习,把本次的内容再次梳理了一遍,怎么递如何归。
三.迭代(循环)
但是递归有个缺陷,就是当产生大量计算的话,比如求40!的阶乘或者50!阶乘递归会出错,溢出,返回不正常的数据,这个时候递归的效率就比较低下,可以考虑用迭代(也可以理解为循环)。递归有时候比非递归的形式更好,逻辑更清晰。所以当递归所表达出来的效果不如意,那么就必须要用非递归,比如循环方式来实现。可能讲的有点绕,希望能够理解。
四.总结
归根结底以上内容是本人反复敲,反复出错后的经验贴,希望对还没遇到问题的有个提示作用,对有问题的能帮助到大家,程序猿的世界是奇妙的,需要不断去实践,才能出真知。