递归的简单概念:函数调用自己。
递归类似于数学里面数列的递推公式。
试想一个主函数调用自己,那就会无限死循环主函数操作,这肯定是不满足要求的。所以使用递归应该要满足某些条件:①当满足某些条件时,递归停止②每次递归完成后要靠近该条件
例题一:用递归写出n的阶乘。
第一步:写个主函数
第二步:利用递归写出factorial函数
以此类推,求n以前的阶乘和就可以写成:
例题二:输入一个整数,按顺序输出每一位。
思考:模10除10可以逆序输出这个数字,但是这里要顺序输出🤔
那么,如果能用递归去算:
那么这个代码就可以完成我们顺序打印的要求了。
具体递归过程:
递归的一些问题:
在C语言中每⼀次函数调用,都要需要为本次函数调用在栈区申请一块内存空间来保存函数调用期间的各种局部变量的值,这块空间被称为运行时堆栈,或者函数栈帧。
函数不返回,函数对应的栈帧空间就⼀直占用,所以如果函数调用中存在递归调用的话,每一次递归函数调用都会开辟属于自己的栈帧空间,直到函数递归不再继续,开始回归,才逐层释放栈帧空间。
所以如果采用函数递归的方式完成代码,递归层次太深,就会浪费太多的栈帧空间,也可能引起栈溢出(stack overflow)的问题。
迭代
再次思考阶乘问题,其实利用循环也能完成:
其好处是不容易发生栈溢出的问题,并且这个过程更高效。
例题三:求第n个斐波那契数列的数
先尝试用递归:
成功实现,但是有个问题,我们来看看第三个斐波那契数列被算了几次
也就是说,在此过程中,只是F(3)就被算了3900万次,这个计算是冗余复杂且无用的,所以我们说递归的效率低下。
所以我们用迭代来写:
思路:
a=1,b=1,a+b→c
b→a,c→b,a+b→c
故该代码按这个思路写也是很容易的
总的来说,选择递归还是迭代需要具体思考。