【C语言深度剖析】深入理解C语言中函数的递归算法

简介: 【C语言深度剖析】深入理解C语言中函数的递归算法

文章目录

定义

递归: 一个函数在它的函数体内调用它自身,这种调用过程称为递归,这种函数称为递归函数

在递归调用中,主调函数又同时是被调函数。执行递归函数将反复调用其自身,每调用一次就进入新的一层

难点

运行递归函数将无休止地调用其自身,这当然是不正确的!

为了防止递归调用无终止的进行,就必须在函数内有终止递归的条件判断语句,满足某种条件后就不再作递归调用,然后逐层返回!!!

这也是递归不易理解的一个难点!

举例说明

我这里通过举例来说明这个递归是如何使用的吧

例题一

接受一个整型值(无符号),按照顺序打印它的每一位。

例如:

输入:1234,输出 1 2 3 4

代码如下:

#include <stdio.h>
void Print(unsigned int n)
{
    if (n > 9)
    {
        Print(n / 10);
    }
    printf("%d ", n % 10);
}
int main()
{
    unsigned int num = 0;
    scanf("%u", &num);
    Print(num);
    return 0;
}

分析:

我这里画了一个图,配合下面的解析看,如图:(红色表示递,绿色表示归)

image.png

当我们走到主函数里面的时候,我们先输入一个数字:123,那么num = 123

然后就调用我们的Print(num)函数,此时我们就叫做递出去

图A:

  • 所以此时的图A当中的n = 123,然后判断if语句:123 > 9为真,进入内部,然后调用Print(n / 10)函数
  • 这次调用的Print函数就走到了图B,此时我们传进去的就是:123 / 10 的结果,也就是12

图B:

  • 所以图B中的n = 12,然后判断if语句:12 > 9为真,进入内部,那么又要调用Print(n / 10)函数
  • 这次调用的Print的函数就走到了图C,此时我们传进去的就是:12 / 10 的结果,也就是1

图C:

  • 所以图C中的n = 1,然后判断if语句:1 > 9为假,所以直接执行print语句,1 % 10 = 1,那么就会在屏幕上打印1和空格

图B:

  • 此时我们图C中的函数已经调用完了,那么就要回归到图B函数中,执行图B中的printf语句,而图B中的n = 12
    那么12 % 10 = 2,然后打印2和空格

图A:

  • 此时我们又要从图B回归到图A,执行图A中的printf语句,而图A中的n = 123,那么123 % 10 = 3,然后打印3和空格

主函数:

  • 图A函数执行完以后,又要回归到我们的主函数Print(num),此时我们的函数调用任务已经结束了,屏幕打印输出:1 2 3

这就是递归的过程,递出去,归回来,

例题二

我们再来做一个题检验一下!

有5个学生在一起

问第五个学生多少岁?他说他比第四个学生大2岁;

问第四个学生多少岁?他说比第三个学生大2岁;

问第三个学生多少岁?他说比第二个学生大2岁;

问第二个学生多少岁?他说比第一个学生大2岁;

最后问第一个学生,他说是10岁。

请问第5个学生多少岁?

这里的话我们用递归的思想来做这道题

思考

age(5) = age(4) + 2;

age(4) = age(3) + 2;

age(3) = age(2) + 2;

age(2) = age(1) + 2;

age(1) = 10;

用数学公式表达如下:

    age(n)= 10; (n = 1)
    age(n)= age(n-1) + 2;(n > 1)

可以看到,当n >1时,求第n个学生的年龄的公式是相同的

因此可以用一个函数表示上述关系。如图表示求第5个学生年龄的过程image.png

显然,这是一个递归问题

由图所示,求解可分为两个阶段:

第1阶段是 回溯,即将第n学生的年龄表示为第(n-1)个学生的函数,而第(n-1)个学生的年龄仍然还不知道,还要回溯到第(n-2)个学生的年龄……直到第一个学生的年龄。此时age(1)已知,不必再向前推了。

然后开始第二阶段,采用递归方法,从第一个学生的已知年龄推算出第二个学生的年龄(12岁),从第二个学生的年龄推算出第三个学生的年龄(14岁)……一直推算出第5个学生的年龄(18岁)为止。

也就是说,一个递归的问题可以分为回溯和递归两个阶段。要经历若干步才能求出最后的值。显而易见,如果要求递归过程不是无限制进行下去,必须具有一个结束递归过程的条件。

本例中,age(1)=10,就是使递归结束的条件。

代码如下:

#include <stdio.h>
int age(int n)
{
    int c = 0;
    if (n == 1)
    {
        c = 10;
    }
    else
    {
        c = age(n - 1) + 2;
    }
    return c;
}
int main()
{
    int stu = 0;
    stu = age(5);
    printf("第五个学生的年龄为: %d\n", stu);
    return 0;
}

总结

一个过程或函数在其定义或说明中有直接或间接调用自身的一种方法

它通常把一个大型复杂的问题层层转化为一个与原问题相似的规模较小的问题来求解

递归策略只需少量的程序就可描述出解题过程所需要的多次重复计算,大大地减少了程序的代码量

递归的主要思考方式在于: 把大事化小


相关文章
|
2月前
|
算法 机器人 定位技术
【VRPTW】基于matlab秃鹰算法BES求解带时间窗的骑手外卖配送路径规划问题(目标函数:最优路径成本 含服务客户数量 服务时间 载量 路径长度)(Matlab代码实现)
【VRPTW】基于matlab秃鹰算法BES求解带时间窗的骑手外卖配送路径规划问题(目标函数:最优路径成本 含服务客户数量 服务时间 载量 路径长度)(Matlab代码实现)
|
1月前
|
机器学习/深度学习 传感器 算法
基于matlab瞬态三角哈里斯鹰算法TTHHO多无人机协同集群避障路径规划(目标函数:最低成本:路径、高度、威胁、转角)(Matlab代码实现)
基于matlab瞬态三角哈里斯鹰算法TTHHO多无人机协同集群避障路径规划(目标函数:最低成本:路径、高度、威胁、转角)(Matlab代码实现)
|
1月前
|
存储 C语言
`scanf`是C语言中用于按格式读取标准输入的函数
`scanf`是C语言中用于按格式读取标准输入的函数,通过格式字符串解析输入并存入指定变量。需注意输入格式严格匹配,并建议检查返回值以确保读取成功,提升程序健壮性。
730 0
|
2月前
|
机器学习/深度学习 算法 数据挖掘
【配送路径规划】基于螳螂虾算法MShOA求解带时间窗的骑手外卖配送路径规划问题(目标函数:最优路径成本 含服务客户数量 服务时间 载量 路径长度)研究(Matlab代码实现)
【配送路径规划】基于螳螂虾算法MShOA求解带时间窗的骑手外卖配送路径规划问题(目标函数:最优路径成本 含服务客户数量 服务时间 载量 路径长度)研究(Matlab代码实现)
|
2月前
|
算法 Python
【配送路径规划】基于遗传算法求解带时间窗的电动汽车配送路径规划(目标函数:最小成本;约束条件:续驶里程、额定载重量、数量、起始点)研究(Matlab代码实现)
【配送路径规划】基于遗传算法求解带时间窗的电动汽车配送路径规划(目标函数:最小成本;约束条件:续驶里程、额定载重量、数量、起始点)研究(Matlab代码实现)
|
3月前
|
安全 C语言
C语言中的字符、字符串及内存操作函数详细讲解
通过这些函数的正确使用,可以有效管理字符串和内存操作,它们是C语言编程中不可或缺的工具。
258 15
|
9月前
|
存储 算法 C语言
【C语言程序设计——函数】素数判定(头歌实践教学平台习题)【合集】
本内容介绍了编写一个判断素数的子函数的任务,涵盖循环控制与跳转语句、算术运算符(%)、以及素数的概念。任务要求在主函数中输入整数并输出是否为素数的信息。相关知识包括 `for` 和 `while` 循环、`break` 和 `continue` 语句、取余运算符 `%` 的使用及素数定义、分布规律和应用场景。编程要求根据提示补充代码,测试说明提供了输入输出示例,最后给出通关代码和测试结果。 任务核心:编写判断素数的子函数并在主函数中调用,涉及循环结构和条件判断。
417 23
|
8月前
|
人工智能 Java 程序员
一文彻底搞清楚C语言的函数
本文介绍C语言函数:函数是程序模块化的工具,由函数头和函数体组成,涵盖定义、调用、参数传递及声明等内容。值传递确保实参不受影响,函数声明增强代码可读性。君志所向,一往无前!
230 1
一文彻底搞清楚C语言的函数
|
9月前
|
算法 C语言
【C语言程序设计——函数】利用函数求解最大公约数和最小公倍数(头歌实践教学平台习题)【合集】
本文档介绍了如何编写两个子函数,分别求任意两个整数的最大公约数和最小公倍数。内容涵盖循环控制与跳转语句的使用、最大公约数的求法(包括辗转相除法和更相减损术),以及基于最大公约数求最小公倍数的方法。通过示例代码和测试说明,帮助读者理解和实现相关算法。最终提供了完整的通关代码及测试结果,确保编程任务的成功完成。
326 15
【C语言程序设计——函数】利用函数求解最大公约数和最小公倍数(头歌实践教学平台习题)【合集】
|
9月前
|
C语言
【C语言程序设计——函数】亲密数判定(头歌实践教学平台习题)【合集】
本文介绍了通过编程实现打印3000以内的全部亲密数的任务。主要内容包括: 1. **任务描述**:实现函数打印3000以内的全部亲密数。 2. **相关知识**: - 循环控制和跳转语句(for、while循环,break、continue语句)的使用。 - 亲密数的概念及历史背景。 - 判断亲密数的方法:计算数A的因子和存于B,再计算B的因子和存于sum,最后比较sum与A是否相等。 3. **编程要求**:根据提示在指定区域内补充代码。 4. **测试说明**:平台对代码进行测试,预期输出如220和284是一组亲密数。 5. **通关代码**:提供了完整的C语言代码实现
171 24