029. 编写递归函数

在C语言中,递归函数是一种调用自身的函数。递归是一种强大的编程技术,适用于解决可以分解为更小子问题的问题。递归函数通常包含两个主要部分:基准情况(Base Case)和递归步骤(Recursive Step)**。

1. 基准情况

基准情况是递归函数的终止条件,用于防止无限递归。当问题规模缩小到一定程度时,基准情况被触发,递归停止。

2. 递归步骤

递归步骤是函数调用自身的过程,每次调用都试图将问题分解为更小的子问题,直到达到基准情况。

示例1:计算阶乘

计算一个非负整数的阶乘是一个经典的递归问题。阶乘的定义如下:

  • n!=n×(n−1)×(n−2)×…×1

  • 0!=1

递归实现

#include <stdio.h>

// 递归函数:计算阶乘
int factorial(int n) {
    // 基准情况
    if (n == 0) {
        return 1;
    }
    // 递归步骤
    return n * factorial(n - 1);
}

int main() {
    int num;

    printf("Enter a non-negative integer: ");
    scanf("%d", &num);

    if (num < 0) {
        printf("Invalid input. Please enter a non-negative integer.\n");
    } else {
        printf("Factorial of %d is %d\n", num, factorial(num));
    }

    return 0;
}

输出结果

假设用户输入5,输出结果为:

Enter a non-negative integer: 5
Factorial of 5 is 120

示例2:计算斐波那契数列

斐波那契数列是一个经典的递归问题,定义如下:

  • F(0)=0

  • F(1)=1

  • F(n)=F(n−1)+F(n−2) 对于 n≥2

递归实现

#include <stdio.h>

// 递归函数:计算斐波那契数列
int fibonacci(int n) {
    // 基准情况
    if (n == 0) {
        return 0;
    } else if (n == 1) {
        return 1;
    }
    // 递归步骤
    return fibonacci(n - 1) + fibonacci(n - 2);
}

int main() {
    int num;

    printf("Enter a non-negative integer: ");
    scanf("%d", &num);

    if (num < 0) {
        printf("Invalid input. Please enter a non-negative integer.\n");
    } else {
        printf("Fibonacci number at position %d is %d\n", num, fibonacci(num));
    }

    return 0;
}

输出结果

假设用户输入6,输出结果为:

Enter a non-negative integer: 6
Fibonacci number at position 6 is 8

示例3:递归遍历链表

假设我们有一个链表,需要递归地遍历并打印链表中的每个元素。

定义链表节点

#include <stdio.h>
#include <stdlib.h>

struct Node {
    int data;
    struct Node *next;
};

递归遍历链表

// 递归函数:遍历链表
void printList(struct Node *head) {
    // 基准情况
    if (head == NULL) {
        return;
    }
    // 递归步骤
    printf("%d -> ", head->data);
    printList(head->next);
}

int main() {
    // 创建链表
    struct Node *head = (struct Node *)malloc(sizeof(struct Node));
    head->data = 1;
    head->next = (struct Node *)malloc(sizeof(struct Node));
    head->next->data = 2;
    head->next->next = (struct Node *)malloc(sizeof(struct Node));
    head->next->next->data = 3;
    head->next->next->next = NULL;

    // 递归遍历链表并打印
    printList(head);
    printf("NULL\n");

    // 释放链表内存
    struct Node *current = head;
    while (current != NULL) {
        struct Node *temp = current;
        current = current->next;
        free(temp);
    }

    return 0;
}

输出结果

1 -> 2 -> 3 -> NULL

示例4:递归计算数组的和

假设我们有一个数组,需要递归地计算数组中所有元素的和。

递归实现

#include <stdio.h>

// 递归函数:计算数组的和
int sumArray(int arr[], int size) {
    // 基准情况
    if (size == 0) {
        return 0;
    }
    // 递归步骤
    return arr[size - 1] + sumArray(arr, size - 1);
}

int main() {
    int arr[] = {1, 2, 3, 4, 5};
    int size = sizeof(arr) / sizeof(arr[0]);

    printf("Sum of array elements is %d\n", sumArray(arr, size));

    return 0;
}

输出结果

Sum of array elements is 15

注意事项

  1. 基准情况:确保递归函数有明确的基准情况,以防止无限递归。
  2. 递归深度:递归函数的调用深度不应过大,否则可能导致栈溢出。
  3. 效率:递归函数可能不如迭代函数高效,因为每次递归调用都会增加函数调用的开销。

通过上述示例,你可以看到如何在C语言中编写递归函数:

  1. 定义基准情况:递归函数的终止条件。
  2. 定义递归步骤:将问题分解为更小的子问题。
  3. 调用自身:递归函数在递归步骤中调用自身。

视频讲解

BiliBili: 视睿网络-哔哩哔哩视频 (bilibili.com)