目录
简单来说,在C语言中,递归就是函数自己调用自己。
递归的思考方式就是把大事化小的过程;递归中的递就是递推的意思,归就是回归的意思。
- 递归存在限制条件,当满足这个限制条件的时候,递归便不在继续。
- 每次递归调用之后越来越接近这个限制条件。
一个正整数的阶乘是所有小于及等于该数的正整数的积,并且0的阶乘为1。
自然数n的阶乘写作n!。
题目:计算n的阶乘(不考虑溢出),n的阶乘就是1~n的数字累积相乘。
我们知道n的阶乘的公式:n!=n*n(n-1)!。
就是说,当n==0的时候,n的阶乘就是1,其余n的阶乘都是可以通过公式计算的。
网址:举例1:求n的阶乘
输入一个整数m,按照顺序打印整数的每一位。
比如:
输入:1234 | 输出:1234 |
输入:520 | 输出:520 |
如果n是一位数,n的每一位就是n自己;n是超过1位数的话,就必须拆分每一位。
1234%10~4,然后1234/10~123,即去掉了4;
然后继续对123%10~3,123/10~12,即去掉了3,以此类推。
在这个解题的过程中,我们就是使⽤了⼤事化⼩的思路。
网址:分析和代码实现
把Print(1234) 打印1234每⼀位,拆解为⾸先Print(123)打印123的每⼀位,再打印得到的4。
把Print(123) 打印123每⼀位,拆解为⾸先Print(12)打印12的每⼀位,再打印得到的3。
直到Print打印的是⼀位数,直接打印就⾏。
事实上,递归是一种很好的编程技巧。但是,在C语言中每一次调用,都需要为本次函数调用在内存的栈区,申请一块内存空间来保存函数调用期间的各种局部变量的值,这块空间就被称为运行时堆栈,或者函数堆帧。
函数不返回,函数对应的堆帧空间就一直占用,所以如果函数调用中存在递归调用的话,每一次递归函数调用都会开辟数以自己的堆帧空间,直到函数递归不在继续,开始回归,才逐层释放堆帧空间。
所以如果采用函数递归的方式完成代码,递归层次太深,就会浪费太多的堆帧空间,也可能引起堆帧溢出的问题。
我们也能举出更加极端的例⼦,就像计算第n个斐波那契数,是不适合使⽤递归求解的,但是斐波那契数的问题通过是使⽤递归的形式描述的,如下:
当我们n输⼊为50的时候,需要很⻓时间才能算出结果,这个计算所花费的时间,是我们很难接受的, 这也说明递归的写法是⾮常低效的,那是为什么呢?
其实递归程序会不断的展开,在展开的过程中,我们很容易就能发现,在递归的过程中会有重复计算,⽽且递归层次越深,冗余计算就会越多。
在计算第40个斐波那契数的时候,使⽤递归⽅式,第3个斐波那契数就被重复计算了。
39088169次,这些计算是⾮常冗余的。所以斐波那契数的计算,使⽤递归是⾮常不明智的,我们就得想迭代的⽅式解决。