C语言 —— 愿文明如薪火般光辉光耀 - 函数递归

[复制链接]
发表于 2025-10-20 10:31:30 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

×
目次

1. 递归的概念
1.1 递归的限定条件
2. 递归举例
   举例1:求n的阶乘
举例2:序次打印⼀个整数的每⼀位


1. 递归的概念

   什么是递归?在C语言中,递归就是函数自己调用自己,给一个简单的递归代码:
  1. #include <stdio.h>
  2. int main()
  3. {
  4.         printf("hehe\n");
  5.         main();//main函数中⼜调⽤了main函数
  6.         return 0;
  7. }
复制代码
  上面这个代码的函数递归没有限定条件,以是会不停无穷循环调用下去,代码终极就会陷入死循环,导致栈溢出(Stack overflow)
  

   总结:递归着实就像是把⼀个⼤型复杂题目层层转化为⼀个与原题目相似,但规模较⼩的⼦题目来求解;直到⼦题目不能再被拆分,递归就竣事了
       
  以是递归的思考⽅式就是把⼤事化⼩的过程
      
递归中的递就是递推的意思,归就是回归的意思

  


1.1 递归的限定条件

   我们在前面的代码说过由于没有限定条件,以是代码进入了死循环,那么我们接下来来聊一聊递归的2个限定条件:
       
1. 递归存在限定条件,当满⾜这个限定条件的时间,递归便不再继续

      
2. 每次递归调⽤之后越来越靠近这个限定条件

  


2. 递归举例

   
举例1:求n的阶乘


   我们知道n的阶乘的公式: n! = n ∗(n −1)!
    
  题⽬:盘算n的阶乘(不思量溢出),n的阶乘就是1~n的数字累积相乘
    ⼀个正整数的阶乘(factorial)是全部⼩于及便是该数的正整数的积,而且0的阶乘为1,
⾃然数n的阶乘写作n!

     
  1. 5! = 5*4*3*2*1
  2. 4! = 4*3*2*1
  3. 所以:5! = 5*4!
  4. 这样的思路就是把⼀个较⼤的问题,转换为⼀个与原问题相似,但规模较⼩的问题来求解的
复制代码
当 n==0 的时间,n的阶乘是1,别的n的阶乘都是可以通过公式盘算
      
  n的阶乘的递归公式如下:
    
  

    那我们就可以写出函数Fact求n的阶乘,假设Fact(n)就是求n的阶乘,那么Fact(n-1)就是求n-1的阶乘,函数如下:
   
  1. int Fact(int n)
  2. {
  3.         if (n == 0)
  4.                 return 1;
  5.         else
  6.                 return n * Fact(n - 1);
  7. }
复制代码
  1. #define _CRT_SECURE_NO_WARNINGS#include <stdio.h>int Fact(int n)
  2. {
  3.         if (n == 0)
  4.                 return 1;
  5.         else
  6.                 return n * Fact(n - 1);
  7. }int main(){        int n = 0;        scanf("%d", &n);        int ret = Fact(n);        printf("%d\n", ret);        return 0;}
复制代码
运行效果:

我们来分析一下这个代码的函数递归过程:

   

  

举例2:序次打印⼀个整数的每⼀位

   输⼊⼀个整数m,打印这个按照序次打印整数的每⼀位
   
⽐如:

     
输⼊:1234 输出:1 2 3 4
输⼊:520 输出:5 2 0

    我们可以1234%10就能得到4,然后1234/10得到123,这就相当于去掉了4,然后继续对123%10,就得到了3,再除10去掉3,以此类推不停的 %10 和 /10 利用,直到1234的每⼀位都得到
    
  但是这⾥有个题目就是得到的数字序次是倒着的
     
于是我们有了灵感,我们发现着实⼀个数字的最低位是最容易得到的,通过%10就能得到
那我们假假想写⼀个函数Print来打印n的每⼀位,如下表现:

    
  1. Print(n)
  2. //如果n是1234,那表⽰为
  3. Print(1234) //打印1234的每⼀位
  4. //其中1234中的4可以通过 % 10得到,那么
  5. Print(1234)就可以拆分为两步:
  6. 1. Print(1234 / 10) //打印123的每⼀位
  7. 2. printf(1234 % 10) //打印4
  8. 完成上述2步,那就完成了1234每⼀位的打印
  9. 那么Print(123)⼜可以拆分为Print(123 / 10) + printf(123 % 10)
复制代码
以此类推:
      
  1.     Print(1234)
  2. ==>Print(123)                   +printf(4)
  3. ==>Print(12)          + printf(3)
  4. ==>Print(1) + printf(2)
  5. ==>printf(1)
复制代码
直到被打印的数字酿成⼀位数的时间,就不须要再拆分,递归竣事
  1. void Print(int n)
  2. {
  3.    if(n>9)
  4.    {
  5.       Print(n/10);
  6.    }
  7.    printf("%d ", n%10);
  8. }
  9. int main()
  10. {
  11.      int m = 0;
  12.      scanf("%d", &m);
  13.      Print(m);
  14.      return 0;
  15. }
复制代码

   在这个解题的过程中,我们就是使⽤了⼤事化⼩的思绪
     
把Print(1234) 打印1234每⼀位,拆解为⾸先Print(123)打印123的每⼀位,再打印得到的4

      
把Print(123) 打印123每⼀位,拆解为⾸先Print(12)打印12的每⼀位,再打印得到的3

      
直到Print打印的是⼀位数,直接打印就⾏

  




完结撒花~
回复

使用道具 举报

登录后关闭弹窗

登录参与点评抽奖  加入IT实名职场社区
去登录
快速回复 返回顶部 返回列表