• C语言函数递归调用


    1、函数递归调用的定义

    递归函数定义:一个函数在 自己的函数体内 调用自己;执行递归函数将反复调用其自身,每调用一次就有一个新层

    1. #include
    2. // 函数声明
    3. void diguifunc();
    4. int main() //主函数
    5. {
    6. diguifunc(); //运行后程序会崩溃,资源耗尽了
    7. }
    8. // 递归函数的定义
    9. void diguifunc()
    10. {
    11. int tempvar1 = 150; //局部变量:在函数内部定义的变量,当函数整个执行完毕后,局部变量所占的内存会被系统自动回收,回收后该局部变量就不可以再使用了。
    12. printf("diguifunc函数执行-----\n");
    13. diguifunc();
    14. }
    15. // 调用栈(一块系统分配给咱们这个程序有特殊用途的内存):就是把形式参数,函数调用关系,局部变量等进行保存在栈里面。
    16. 这段内存是有限的,如果一旦超过这个内存大小,就会出现崩溃现象。

    函数递归调用运行图:

    2、递归调用的出口

    因为上面这种递归调用会产生死循环,所以这种自己调用自己的方式必须要有一个出口,这个出口也叫做递归结束条件,从而能够让这种函数调用结束。

    范例:计算5的阶乘,其实就是计算 1*2*3*4*5,

    我们并不知道5的阶乘是多少,但是我们知道一点,4的阶乘 * 5他就等于5的阶乘。

    我们并不知道4的阶乘是多少,但是我们知道一点,3的阶乘 * 4他就等于4的阶乘。

    我们并不知道3的阶乘是多少,但是我们知道一点,2的阶乘 * 3他就等于3的阶乘。

    所以递归调用的出口肯定是在1的阶乘,因为1的阶乘是1,可以作为出口,我们能够求出2的阶乘,也就是1*2;以此类推瑞。

    1. #include
    2. // 函数声明
    3. int dg_jiecheng(int n);
    4. int main() //主函数
    5. {
    6. int result = dg_jiecheng(5);
    7. printf("result=%d\n",result); // 结果为120
    8. }
    9. // 函数定义
    10. int dg_jiecheng(int n)
    11. {
    12. int result; // 局部变量,保存阶乘结果
    13. if(n==1) // 1的阶乘就是1
    14. {
    15. return 1; // 这里就是该递归调用的出口
    16. }
    17. else
    18. {
    19. // 第一次是 result = dg_jiecheng(4)*5,然后进入到了 dg_jiecheng(4),这行代码就被暂存了;
    20. 第二次是 result = dg_jiecheng(3)*4,然后进入到了 dg_jiecheng(3),这行代码就被暂存了;
    21. 第三次是 result = dg_jiecheng(2)*3,然后进入到了 dg_jiecheng(2),这行代码就被暂存了;
    22. 第四次是 result = dg_jiecheng(1)*2,然后进入到了 dg_jiecheng(1),这行代码就被暂存了;
    23. 此时,dg_jiecheng(1)的出口条件成立了,终于,能够执行return 1,这可是 return 语句第一次捞着执行。
    24. 第一次:return 1,返回的是1,返回到dg_jiecheng(2)这里:
    25. return =1*2 并且也执行return result;,返回1*2=2
    26. 返回到dg_jiecheng(3)这里:
    27. return =2 并且也执行return result;,返回2*3=6
    28. 返回到dg_jiecheng(4)这里:
    29. return =6 并且也执行return result;,返回6*4=24
    30. 返回到dg_jiecheng(5)这里:
    31. return =24 并且也执行return result;,返回24*5=120
    32. result = dg_jiecheng(n-1)* n;
    33. }
    34. return result;
    35. }

    3、递归的优缺点

    优点:

            代码少,代码看起来简洁,精妙。

    缺点:

            虽然代码简洁,精妙,但是不好理解。

             如果调用的层次太深,调用栈(内存),可能会溢出,如果真出现这种情况,那么说明不能用递归解决该问题。

            效率和性能都不高,这深层次的调用,要保存的东西很多,所以效率和性能肯定高不起来。有些问题用不用递归都行,有些问题可能必须用递归解决。汉诺塔

             递归函数的直接和间接调用:

    递归函数的直接调用:调用递归函数f的过程中,f函数有调用自己,这就是直接调用。

    递归函数的间接调用:调用函数f1的过程中要调用f2函数,然后f2函数又调用f1函数,这就是间接调用。

  • 相关阅读:
    NL6621 实现获取天气情况
    33、用户查询缓存(缓存雪崩)
    JS中数组随机排序实现(原地算法sort/shuffle算法)
    比较三种非破坏性处理数组的方法
    自然语言处理的多行业应用
    使用vite和vue-i18n,实现部署后更新多语言功能
    猿创征文|给设备做一个独立自主的小APP-实例详解
    JVM参数调优推荐
    NGINX配置SSL支持
    std::map中的自定义key避免踩坑
  • 原文地址:https://blog.csdn.net/qq_48516121/article/details/126902748