问小白 wenxiaobai
资讯
历史
科技
环境与自然
成长
游戏
财经
文学与艺术
美食
健康
家居
文化
情感
汽车
三农
军事
旅行
运动
教育
生活
星座命理

C语言递归详解:从概念到实战

创作时间:
作者:
@小白创作中心

C语言递归详解:从概念到实战

引用
CSDN
1.
https://m.blog.csdn.net/good_afternoon6/article/details/145952042

递归是编程中一个非常重要的概念,它允许函数调用自身来解决问题。本文将通过多个实例,深入浅出地讲解递归的原理、实现方法及其优缺点,帮助读者全面理解这一编程技巧。

1. 什么是递归?

递归是一种在函数定义中直接调用自身的编程技术。想象一个小时候常听的故事:“从前有座山,山上有座庙,庙里有个老和尚,老和尚在给小和尚讲故事,故事讲的是从前有座山,山上有座庙……”这个故事就是一个递归的例子。在编程中,递归函数的核心在于将大问题分解成小问题,然后通过解决这些小问题来解决大问题。

2. 递归示例:计算阶乘

2.1 分析

对于一个正整数 n,其阶乘可以通过连乘积来定义:n! = 1 * 2 * … * (n-1) * n,并且规定 0! = 1。例如,4! = 1 * 2 * 3 * 45! = 1 * 2 * 3 * 4 * 5。观察这些计算过程,可以发现 5! = 4! * 56! = 5! * 6,以此类推,可以推导出 n! = (n - 1)! * n。这个过程可以一直递推到 1! = 0! * 1,因为 0! = 1,所以 1! = 1,然后逐层返回计算结果。

这个过程可以用一句话来概括:“不撞南墙不回头”。如果把代码运行的流程比作一个人,那么那堵南墙就是 0! = 1,只有代码执行碰到这堵墙才会回头返回值。我们把一直前进的过程叫“递”,把在撞完南墙后返回的过程叫“归”。

2.2 代码展示

#include <stdio.h>

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

int main() {
    int n;
    printf("请输入一个正整数:");
    scanf("%d", &n);
    printf("%d! = %d\n", n, factorial(n));
    return 0;
}

3. 执行递归的条件

递归必须存在限制条件,否则就会像开头的故事一样永远停不下来。每次递归调用函数时都会向内存栈区申请一块空间,如果没有限制条件,就会一直申请空间,最终导致栈溢出。

4. 递归的优缺点

通过计算斐波那契数列的例子来体会递归的优缺点。斐波那契数列的定义是从0和1开始,后续的每一项都是前两项的和,即1、1、2、3、5、8、13、21、34……

递归的缺点:

  1. 可能会占用很多的栈区空间,浪费内存
  2. 效率较低,在数据量较大时,会多次重复计算数据

递归的优点:

  1. 代码简洁,易于理解
  2. 根据公式就能快速编写出递归函数

5. 练习推荐:汉诺塔问题

汉诺塔问题是递归的经典案例。有三根柱子A、B、C,初始时在A柱上按顺序从上到下叠放着n个盘子。目标是将所有盘子移动到C柱上,且移动过程中需满足以下规则:

  1. 每次只能移动一个盘子;
  2. 大盘子不能放在小盘子上面。

下面是汉诺塔问题的递归实现代码:

#include <stdio.h>

// 定义递归函数hanoi,参数分别为盘子数量n、起始柱a、目标柱c、辅助柱b
void hanoi(int n, char a, char c, char b) {
    // 递归终止条件:当n=1时,直接将盘子从a移动到c
    if (n == 1) {
        printf("Move disk 1 from %c to %c\n", a, c);
        return;
    }
    // 将n-1个盘子从a移动到b,借助c柱
    hanoi(n - 1, a, b, c);
    // 将第n个盘子从a移动到c
    printf("Move disk %d from %c to %c\n", n, a, c);
    // 将n-1个盘子从b移动到c,借助a柱
    hanoi(n - 1, b, c, a);
}

int main() {
    int n;
    printf("请输入盘子的数量: ");
    scanf("%d", &n);
    printf("汉诺塔移动过程如下:\n");
    hanoi(n, 'A', 'C', 'B'); // 调用递归函数
    return 0;
}

递归是编程学习中一个比较难但非常重要的知识点,希望这篇文章能帮助大家更深刻地理解递归。

© 2023 北京元石科技有限公司 ◎ 京公网安备 11010802042949号