递归函数详解


1. 什么是递归函数

一个函数在它的函数体内调用它自身称为递归调用,这种函数称为递归函数。执行递归函数将反复调用其自身,每调用一次就进入新的一层,当最内层的函数执行完毕后,再一层一层地由里到外退出。

一句话总结递归:自我调用且有完成状态


2. 递归求阶乘

举个例子,我们来计算阶乘n! = 1 x 2 x 3 x ... x n,用函数factorial(n)表示,可以看出:
在这里插入图片描述
所以,factorial(n)可以表示为n x factorial(n-1),只有n=1时需要特殊处理。

于是,factorial(n)用递归的方式写出来就是:

#include <stdio.h>
//求n的阶乘
long factorial(int n) 
{
    if (n == 1)
    {
        return 1;
    }
    else 
    {
        return factorial(n - 1) * n;  // 递归调用
    }
}
int main() 
{
    int a;
    printf("Input a number: ");
    scanf("%d", &a);
    printf("Factorial(%d) = %ld\n", a, factorial(a));
    return 0;
}

运行结果:

Input a number: 5↙
Factorial(5) = 120

factorial()就是一个典型的递归函数。调用factorial()后即进入函数体,只有当 n == 1 时函数才会执行结束,否则就一直调用它自身。

如果我们计算factorial(5),可以根据函数定义看到计算过程如下:

===> fact(5)
===> 5 * fact(4)
===> 5 * (4 * fact(3))
===> 5 * (4 * (3 * fact(2)))
===> 5 * (4 * (3 * (2 * fact(1))))
===> 5 * (4 * (3 * (2 * 1)))
===> 5 * (4 * (3 * 2))
===> 5 * (4 * 6)
===> 5 * 24
===> 120

要想理解递归函数,重点是理解它是如何逐层进入,又是如何逐层退出的,下面我们以 5! 为例进行讲解。


3. 递归的进入

  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() 函数了,递归就结束了。
    在这里插入图片描述


4. 递归的退出

递归进入到最内层的时候,递归就结束了,就开始逐层退出了,也就是 逐层执行 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!的值。
    在这里插入图片描述


5. 递归的条件

每一个递归函数都应该只进行有限次的递归调用,否则它就会进入死循环,永远都不能退出了,还会导致栈溢出

要想让递归函数逐层进入再逐层退出,需要解决两个方面的问题:

  • 存在结束条件:当符合结束条件时递归便不再继续。对于 factorial(),当形参 n 等于 0 或 1 时,递归就结束了。
  • 存在递推关系:每次递归调用之后越来越接近结束条件。对于 factorial(),每次递归调用的实参为 n - 1,这会使得形参 n 的值逐渐减小,越来越趋近于 1 或 0。

文章参考:
http://c.biancheng.net/view/1861.html
https://www.liaoxuefeng.com/wiki/1016959663602400/1017268131039072

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值