- C编程教程
- C - 首页
- C语言基础
- C - 概述
- C - 特性
- C - 历史
- C - 环境搭建
- C - 程序结构
- C - Hello World
- C - 编译过程
- C - 注释
- C - 词法单元
- C - 关键字
- C - 标识符
- C - 用户输入
- C - 基本语法
- C - 数据类型
- C - 变量
- C - 整数提升
- C - 类型转换
- C - 类型强制转换
- C - 布尔类型
- C语言中的常量和字面量
- C - 常量
- C - 字面量
- C - 转义序列
- C - 格式说明符
- C语言中的运算符
- C - 运算符
- C - 算术运算符
- C - 关系运算符
- C - 逻辑运算符
- C - 位运算符
- C - 赋值运算符
- C - 一元运算符
- C - 自增和自减运算符
- C - 三元运算符
- C - sizeof 运算符
- C - 运算符优先级
- C - 其他运算符
- C语言中的决策
- C - 决策
- C - if 语句
- C - if...else 语句
- C - 嵌套 if 语句
- C - switch 语句
- C - 嵌套 switch 语句
- C语言中的循环
- C - 循环
- C - while 循环
- C - for 循环
- C - do...while 循环
- C - 嵌套循环
- C - 无限循环
- C - break 语句
- C - continue 语句
- C - goto 语句
- C语言中的函数
- C - 函数
- C - 主函数
- C - 按值调用函数
- C - 按引用调用函数
- C - 嵌套函数
- C - 可变参数函数
- C - 用户自定义函数
- C - 回调函数
- C - 返回语句
- C - 递归
- C语言中的作用域规则
- C - 作用域规则
- C - 静态变量
- C - 全局变量
- C语言中的数组
- C - 数组
- C - 数组的特性
- C - 多维数组
- C - 将数组传递给函数
- C - 从函数返回数组
- C - 可变长数组
- C语言中的指针
- C - 指针
- C - 指针和数组
- C - 指针的应用
- C - 指针运算
- C - 指针数组
- C - 指向指针的指针
- C - 将指针传递给函数
- C - 从函数返回指针
- C - 函数指针
- C - 指向数组的指针
- C - 指向结构体的指针
- C - 指针链
- C - 指针与数组
- C - 字符指针和函数
- C - 空指针
- C - void 指针
- C - 野指针
- C - 解引用指针
- C - 近、远和巨型指针
- C - 指针数组的初始化
- C - 指针与多维数组
- C语言中的字符串
- C - 字符串
- C - 字符串数组
- C - 特殊字符
- C语言中的结构体和联合体
- C - 结构体
- C - 结构体和函数
- C - 结构体数组
- C - 自引用结构体
- C - 查找表
- C - 点(.)运算符
- C - 枚举(或枚举类型)
- C - 结构体填充和打包
- C - 嵌套结构体
- C - 匿名结构体和联合体
- C - 联合体
- C - 位域
- C - Typedef
- C语言中的文件处理
- C - 输入与输出
- C - 文件I/O(文件处理)
- C预处理器
- C - 预处理器
- C - 指令
- C - 预处理器运算符
- C - 宏
- C - 头文件
- C语言中的内存管理
- C - 内存管理
- C - 内存地址
- C - 存储类
- 其他主题
- C - 错误处理
- C - 可变参数
- C - 命令执行
- C - 数学函数
- C - static 关键字
- C - 随机数生成
- C - 命令行参数
- C编程资源
- C - 问答
- C - 快速指南
- C - 速查表
- C - 有用资源
- C - 讨论
C语言中的递归
递归是指一个函数调用自身的过程。C语言允许编写这样的函数,这些函数通过将复杂问题分解成简单易处理的问题来调用自身以解决复杂问题。这些函数被称为递归函数。
什么是C语言中的递归函数?
C语言中的递归函数是一个函数,它调用自身。当某个问题以自身来定义时,就会使用递归函数。虽然它涉及迭代,但使用迭代方法来解决此类问题可能会很繁琐。递归方法为看似复杂的问题提供了一种非常简洁的解决方案。
语法
一个通用的递归函数看起来像这样:
void recursive_function(){ recursion(); // function calls itself } int main(){ recursive_function(); }
在使用递归时,程序员需要注意定义函数的退出条件,否则它将进入无限循环。
为什么在C语言中使用递归?
递归用于执行复杂的任务,例如树和图结构遍历。流行的递归编程解决方案包括阶乘、二分查找、树遍历、汉诺塔、国际象棋中的八皇后问题等。
递归程序变得简洁,但不容易理解。即使代码的大小可能减少,它也需要更多处理器资源,因为它涉及对函数的多次IO调用。
使用递归计算阶乘
递归函数对于解决许多数学问题非常有用,例如计算数字的阶乘、生成斐波那契数列等。
递归最流行的例子是阶乘的计算。在数学上,阶乘定义为:
n! = n X (n-1)!
可以看出,我们使用阶乘本身来定义阶乘。因此,这是一个适合编写递归函数的案例。让我们扩展上述定义来计算5的阶乘值。
5! = 5 X 4! 5 X 4 X 3! 5 X 4 X 3 X 2! 5 X 4 X 3 X 2 X 1! 5 X 4 X 3 X 2 X 1 = 120
虽然我们可以使用循环执行此计算,但它的递归函数涉及通过递减数字来连续调用自身,直到它达到1。
示例:非递归阶乘函数
以下程序演示了如何使用非递归函数来计算数字的阶乘:
#include <stdio.h> #include <math.h> // function declaration int factorial(int); int main(){ int a = 5; int f = factorial(a); printf("a: %d \n", a); printf("Factorial of a: %d", f); } int factorial(int x){ int i; int f = 1; for (i = 5; i >= 1; i--){ f *= i; } return f; }
输出
运行此代码时,它将产生以下输出:
a: 5 Factorial of a: 120
示例:递归阶乘函数
现在让我们为计算给定数字的阶乘编写一个递归函数。
以下示例使用递归函数计算给定数字的阶乘:
#include <stdio.h> #include <math.h> /* function declaration */ int factorial(int i){ if(i <= 1){ return 1; } return i * factorial(i - 1); } int main(){ int a = 5; int f = factorial(a); printf("a: %d \n", a); printf("Factorial of a: %d", f); return 0; }
输出
运行代码并检查其输出:
a: 5 Factorial of a: 120
当main()函数通过传递变量“a”来调用factorial()函数时,它的值将存储在“i”中。factorial()函数连续调用自身。
在每次调用中,"i"的值在减少1后乘以其先前值,直到它达到1。当它达到1时,从参数的初始值到1之间所有值的乘积将返回到main()函数。
使用递归进行二分查找
让我们再看一个例子来了解递归是如何工作的。手头的问题是在数组中检查给定数字是否存在。
虽然我们可以使用for循环并比较每个数字来对列表中的某个数字进行顺序查找,但顺序查找效率不高,尤其是在列表过长的情况下。
二分查找算法检查索引“start”是否大于索引“end”。根据变量“mid”处的值,再次调用该函数以搜索元素。
我们有一个按升序排列的数字列表。然后我们找到列表的中点,并将检查限制在中点的左侧或右侧,具体取决于所需数字是否小于或大于中点处的数字。
示例:递归二分查找
以下代码实现了递归二分查找技术:
#include <stdio.h> int bSearch(int array[], int start, int end, int element){ if (end >= start){ int mid = start + (end - start ) / 2; if (array[mid] == element) return mid; if (array[mid] > element) return bSearch(array, start, mid-1, element); return bSearch(array, mid+1, end, element); } return -1; } int main(void){ int array[] = {5, 12, 23, 45, 49, 67, 71, 77, 82}; int n = 9; int element = 67; int index = bSearch(array, 0, n-1, element); if(index == -1 ){ printf("Element not found in the array "); } else{ printf("Element found at index: %d", index); } return 0; }
输出
运行代码并检查其输出:
Element found at index: 5
使用递归生成斐波那契数列
在斐波那契数列中,一个数字是其前两个数字的和。要生成斐波那契数列,第i个数字是i-1和i-2的加和。
示例
以下示例使用递归函数为给定数字生成斐波那契数列的前10个数字:
#include <stdio.h> int fibonacci(int i){ if(i == 0){ return 0; } if(i == 1){ return 1; } return fibonacci(i-1) + fibonacci(i-2); } int main(){ int i; for (i = 0; i < 10; i++){ printf("%d\t\n", fibonacci(i)); } return 0; }
输出
编译并执行上述代码时,将产生以下结果:
0 1 1 2 3 5 8 13 21 34
在程序中实现递归对于初学者来说比较困难。虽然任何迭代过程都可以转换为递归过程,但并非所有递归案例都可以轻松地迭代表示。