C语言 —— 愿文明如薪火般灿烂 - 函数递归

目录

[1. 递归的概念](#1. 递归的概念)

[1.1 递归的限制条件](#1.1 递归的限制条件)

[2. 递归举例](#2. 递归举例)

举例1:求n的阶乘

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


1. 递归的概念

什么是递归?在C语言中,递归就是函数自己调用自己,给一个简单的递归代码:

复制代码
#include <stdio.h>

int main()
{
	printf("hehe\n");
	main();//main函数中⼜调⽤了main函数
	return 0;
}

上面这个代码的函数递归没有限制条件,所以会一直无限循环调用下去,代码最终就会陷入死循环,导致栈溢出(Stack overflow)

总结:递归其实就像是把⼀个⼤型复杂问题层层转化为⼀个与原问题相似,但规模较⼩的⼦问题来求解;直到⼦问题不能再被拆分,递归就结束了

所以递归的思考⽅式就是把⼤事化⼩的过程

递归中的递就是递推的意思,归就是回归的意思


1.1 递归的限制条件

我们在前面的代码说过因为没有限制条件,所以代码进入了死循环,那么我们接下来来聊一聊递归的2个限制条件:

1. 递归存在限制条件,当满⾜这个限制条件的时候,递归便不再继续

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


2. 递归举例

举例1:求n的阶乘

我们知道n的阶乘的公式: n! = n ∗(n −1)!

题⽬:计算n的阶乘(不考虑溢出),n的阶乘就是1~n的数字累积相乘
⼀个正整数的阶乘(factorial)是所有⼩于及等于该数的正整数的积,并且0的阶乘为1,
⾃然数n的阶乘写作n!

复制代码
5! = 5*4*3*2*1

4! = 4*3*2*1

所以:5! = 5*4!

这样的思路就是把⼀个较⼤的问题,转换为⼀个与原问题相似,但规模较⼩的问题来求解的

当 n==0 的时候,n的阶乘是1,其余n的阶乘都是可以通过公式计算

n的阶乘的递归公式如下:


那我们就可以写出函数Fact求n的阶乘,假设Fact(n)就是求n的阶乘,那么Fact(n-1)就是求n-1的阶乘,函数如下:

复制代码
int Fact(int n)
{
	if (n == 0)
		return 1;
	else
		return n * Fact(n - 1);
}
复制代码
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>

int Fact(int n)
{
	if (n == 0)
		return 1;
	else
		return n * Fact(n - 1);
}

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的每⼀位,如下表示:

复制代码
Print(n)
//如果n是1234,那表⽰为
Print(1234) //打印1234的每⼀位

//其中1234中的4可以通过 % 10得到,那么
Print(1234)就可以拆分为两步:
1. Print(1234 / 10) //打印123的每⼀位
2. printf(1234 % 10) //打印4

完成上述2步,那就完成了1234每⼀位的打印
那么Print(123)⼜可以拆分为Print(123 / 10) + printf(123 % 10)

以此类推:

复制代码
    Print(1234)
 ==>Print(123)                   +printf(4)
 ==>Print(12)          + printf(3)
 ==>Print(1) + printf(2)
 ==>printf(1)

直到被打印的数字变成⼀位数的时候,就不需要再拆分,递归结束

复制代码
 void Print(int n)
 {
   if(n>9)
   {
      Print(n/10);
   }
   printf("%d ", n%10);
 }

 int main()
 {
     int m = 0;
     scanf("%d", &m);
     Print(m);
     return 0;
 }

在这个解题的过程中,我们就是使⽤了⼤事化⼩的思路

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

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

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


完结撒花~

相关推荐
-dzk-27 分钟前
【代码随想录】LC 59.螺旋矩阵 II
c++·线性代数·算法·矩阵·模拟
韩立学长34 分钟前
【开题答辩实录分享】以《基于Python的大学超市仓储信息管理系统的设计与实现》为例进行选题答辩实录分享
开发语言·python
风筝在晴天搁浅36 分钟前
hot100 78.子集
java·算法
Jasmine_llq40 分钟前
《P4587 [FJOI2016] 神秘数》
算法·倍增思想·稀疏表(st 表)·前缀和数组(解决静态区间和查询·st表核心实现高效预处理和查询·预处理优化(提前计算所需信息·快速io提升大规模数据读写效率
超级大只老咪1 小时前
快速进制转换
笔记·算法
froginwe111 小时前
Scala 循环
开发语言
m0_706653231 小时前
C++编译期数组操作
开发语言·c++·算法
故事和你911 小时前
sdut-Java面向对象-06 继承和多态、抽象类和接口(函数题:10-18题)
java·开发语言·算法·面向对象·基础语法·继承和多态·抽象类和接口
Bruk.Liu2 小时前
(LangChain实战2):LangChain消息(message)的使用
开发语言·langchain
qq_423233902 小时前
C++与Python混合编程实战
开发语言·c++·算法