C语⾔递归函数(递归调⽤)详解[带实例演⽰]
⼀个函数在它的函数体内调⽤它⾃⾝称为这种函数称为。执⾏递归函数将反复调⽤其⾃⾝,每调⽤⼀次就进⼊新的⼀层,当最内层的函数执⾏完毕后,再⼀层⼀层地由⾥到外退出。
递归函数不是C语⾔的 等其他编程语⾔也都⽀持递归函数。
下⾯我们通过⼀个求阶乘的例⼦,看看递归函数到底是如何运作的。阶乘 n! 的计算公式如下:
根据公式编写如下的代码:
1. #include <stdio.h>
2.
3. //求n的阶乘
4. long factorial(int n) {
5. if (n == 0 || n == 1) {
6. return 1;
7. }
8. else {
9. return factorial(n - 1) * n; // 递归调⽤
10. }
递归函数c语言规则11. }
12.
13. int main() {
14. int a;
15. printf("Input a number: ");
16. scanf("%d", &a);
17. printf("Factorial(%d) = %ld\n", a, factorial(a));
18.
19. return 0;
20. }
运⾏结果:
Input a number: 5↙
Factorial(5) = 120
factorial() 就是⼀个典型的递归函数。调⽤ factorial() 后即进⼊函数体,只有当 n==0 或 n==1 时函数才会执⾏结束,否则就⼀直调⽤它⾃⾝。
由于每次调⽤的实参为 n-1,即把 n-1 的值赋给形参 n,所以每次递归实参的值都减 1,直到最后 n-1 的值为 1 时再作递归调⽤,形参 n 的值也为1,递归就终⽌了,会逐层退出。
要想理解递归函数,重点是理解它是如何逐层进⼊,⼜是如何逐层退出的,下⾯我们以 5! 为例进⾏讲
解。
1) 求 5!,即调⽤ factorial(5)。当进⼊ factorial() 函数体后,由于形参 n 的值为 5,不等于 0 或 1,所以执⾏factorial(n-1) * n,也即执⾏factorial(4) * 5。为了求得这个表达式的结果,必须先调⽤ factorial(4),并暂停其他操作。换句话说,在得到 factorial(4) 的结果之前,不能进⾏其他操作。这就是第⼀次递归。
2) 调⽤ factorial(4) 时,实参为 4,形参 n 也为 4,不等于 0 或 1,会继续执⾏factorial(n-1) * n,也即执⾏factorial(3) * 4。为了求得这个表达式的结果,⼜必须先调⽤ factorial(3)。这就是第⼆次递归。
3) 以此类推,进⾏四次递归调⽤后,实参的值为 1,会调⽤ factorial(1)。此时能够直接得到常量 1 的值,并把结果 return,就不需要再次调⽤ factorial() 函数了,递归就结束了。
下表列出了逐层进⼊的过程
层次/层数实参/形参调⽤形式需要计算的表达式需要等待的结果
1n=5factorial(5)factorial(4) * 5factorial(4) 的结果
2n=4factorial(4)factorial(3) * 4factorial(3) 的结果
3n=3factorial(3)factorial(2) * 3factorial(2) 的结果
4n=2factorial(2)factorial(1) * 2factorial(1) 的结果
5n=1factorial(1)1⽆
当递归进⼊到最内层的时候,递归就结束了,就开始逐层退出了,也就是逐层执⾏ return 语句。
1) n 的值为 1 时达到最内层,此时 return 出去的结果为 1,也即 factorial(1) 的调⽤结果为 1。
2) 有了 factorial(1) 的结果,就可以返回上⼀层计算factorial(1) * 2的值了。此时得到的值为 2,return 出去的结果也为 2,也
即 factorial(2) 的调⽤结果为 2。
3) 以此类推,当得到 factorial(4) 的调⽤结果后,就可以返回最顶层。经计算,factorial(4) 的结果为 24,那么表达式factorial(4) * 5的结果为 120,此时 return 得到的结果也为 120,也即 factorial(5) 的调⽤结果为 120,这样就得到了 5! 的值。
下表列出了逐层退出的过程
层次/层数调⽤形式需要计算的表达式从内层递归得到的结果
(内层函数的返回值)
表达式的值
(当次调⽤的结果)
5factorial(1)1⽆1
4factorial(2)factorial(1) * 2factorial(1) 的返回值,也就是 12
3factorial(3)factorial(2) * 3factorial(2) 的返回值,也就是 26
2factorial(4)factorial(3) * 4factorial(3) 的返回值,也就是 624
1factorial(5)factorial(4) * 5factorial(4) 的返回值,也就是 24120
⾄此,我们已经对递归函数 factorial() 的进⼊和退出流程做了深⼊的讲解,把看似复杂的调⽤细节逐⼀呈献给⼤家,即使你是初学者,相信你也能解开谜团。
递归的条件
每⼀个递归函数都应该只进⾏有限次的递归调⽤,否则它就会进⼊死胡同,永远也不能退出了,这样的程序是没有意义的。
要想让递归函数逐层进⼊再逐层退出,需要解决两个⽅⾯的问题:
存在限制条件,当符合这个条件时递归便不再继续。对于 factorial(),当形参 n 等于 0 或 1 时,递归就结束了。
每次递归调⽤之后越来越接近这个限制条件。对于 factorial(),每次递归调⽤的实参为 n - 1,这会使得形参 n 的值逐渐减⼩,越来越趋近于 1 或 0。
factorial() 是最简单的⼀种递归形式——尾递归,也就是递归调⽤位于函数体的结尾处。除了尾递归,还有更加烧脑的两种递归形式,分别是中间递归和多层递归:
中间递归:发⽣递归调⽤的位置在函数体的中间;
多层递归:在⼀个函数⾥⾯多次调⽤⾃⼰。
递归函数也只是⼀种解决问题的技巧,它和其它技巧⼀样,也存在某些缺陷,具体来说就是:递归函数的时间开销和内存开销都⾮常⼤,极端情况下会导致程序崩溃。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论