C语言一个简单递归的实现

C语言一个简单递归的实现

问题的引入

在初中或高中数学问题中会遇到这样的问题,已知f(0) = 1,f(n) = f(n-1)+n (n>=0 且为正整数);求f(3)或放f(n),这样的问题。这实质上就是一个递归问题。
解法如下:
f(3) = f(2) + 3 要求f(3),需要f(2)
f(2) = f(1) + 2 同理f(1)
f(1) = f(0) +1 已知
f(0) = 1
==>f(0) ==>f(1) =>f(2) ==>f(3) = 7
同理f(n)。

c语言实现


下面展示一些 内联代码片


#include <stdio.h>

static int recursion(int n)
{
	int ret;
	if(n == 0)
		return 1;
	else{
		ret = recursion(n-1)+ n;
		n--;
		return ret;
	}
}
int main(void)
{
	printf("recursion(3)=%d\n",recursion(3));
	return 0;
}

编译运行结果如下

recursion(3)=7

阶乘的定义&实现

一个正整数的阶乘(factorial)是所有小于及等于该数的正整数的积,并且0的阶乘为1。自然数n的阶乘写作n!。
亦即n!=1×2×3×…×(n-1)n。阶乘亦可以递归方式定义:0!=1,n!=(n-1)!×n。
代码实现


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

static int recursion(int n)
{
	int ret;
	if(n == 0)
		return 1;
	else{
		ret = recursion(n-1)*n;
		n--;
		return ret;
	}
}
int main(int argc ,char *argv[])
{ 
	if(argc < 2){
		printf("please enter a number (n!)\n");
		return -1;
	}

	printf("recursion(%s)=%d\n",argv[1],recursion( (atoi(argv[1]))));
	return 0;
}

输入参数5得到
recursion(5)=120

以上就是对递归的简单认知和功能代码的基本实现,如有不正确的地方欢迎指正!

<think>我们正在讨论C语言递归函数的实现方法。根据引用[2]和[3],递归函数是一种自己调用自己的函数,通常用于解决可以分解为相似子问题的问题。递归有两个关键阶段:递推和回归。 引用[2]展示了使用循环(非递归实现阶乘的函数,而引用[3]则展示了使用递归计算第n个人年龄的示例(已知第一个人10岁,后面每个人比前一个人大2岁)。 ### 递归函数的基本要素 1. **递归出口(Base Case)**:必须有一个或多个简单情况,函数不再递归调用自身,而是直接返回结果。否则,递归将无限进行,导致栈溢出。 2. **递归步骤(Recursive Step)**:将问题分解为更小的子问题,并通过调用自身来解决这些子问题。 ### 递归函数设计步骤 1. 确定递归终止条件 2. 确定递归关系(如何将大问题分解为小问题) ### 递归函数示例:计算阶乘 阶乘的递归定义: - $n! = 1$ (当$n=0$或$n=1$时) - $n! = n \times (n-1)!$ (当$n>1$时) C语言实现: ```c #include <stdio.h> // 递归计算阶乘 long factorial(int n) { if (n == 0 || n == 1) { // 递归出口 return 1; } else { return n * factorial(n-1); // 递归调用 } } int main() { int n; printf("输入一个整数: "); scanf("%d", &n); printf("%d! = %ld\n", n, factorial(n)); return 0; } ``` ### 递归函数示例:计算斐波那契数列 斐波那契数列定义: - $F(0)=0$ - $F(1)=1$ - $F(n)=F(n-1)+F(n-2)$(当$n \geq 2$时) C语言实现: ```c #include <stdio.h> int fibonacci(int n) { if (n == 0) return 0; // 递归出口 else if (n == 1) return 1; // 递归出口 else return fibonacci(n-1) + fibonacci(n-2); // 递归调用 } int main() { int n; printf("输入项数: "); scanf("%d", &n); printf("斐波那契数列第%d项是: %d\n", n, fibonacci(n)); return 0; } ``` ### 递归函数的注意事项 1. **栈溢出(Stack Overflow)**:每次递归调用都会在调用栈上创建一个新的栈帧,如果递归深度太大,会导致栈溢出。因此,递归深度应有限制,或者考虑使用迭代(循环)代替。 2. **重复计算问题**:如斐波那契数列的递归实现中,存在大量重复计算(如`fibonacci(3)`会被多次计算),效率低下。可通过记忆化(缓存中间结果)或改用迭代优化。 3. **效率问题**:递归可能效率较低,因为函数调用的开销比循环大。但递归通常使代码更简洁易读。 4. **递归出口必须可达**:确保每次递归都向基本情况逼近,否则会导致无限递归。 ### 递归与迭代的选择 - 当问题具有明显的递归结构(如树、图遍历、分治算法)时,递归更自然。 - 若迭代实现更直观且效率更高(如阶乘、斐波那契数列),则优先使用迭代。 ### 调试递归函数 1. 使用调试器逐步跟踪递归调用。 2. 打印递归深度和参数值: ```c int factorial(int n) { static int depth = 0; depth++; printf("深度=%d, n=%d\n", depth, n); if (n<=1) { depth--; return 1; } int result = n * factorial(n-1); depth--; return result; } ``` ### 总结 递归是一种强大的编程技巧,适用于解决分治、回溯等问题。设计递归函数时,务必确保: - 有明确的递归出口 - 每次递归调用都使问题规模减小 - 避免不必要的重复计算 通过引用[3]中的例子,我们看到递归如何将问题分解(回推)并组合结果(递推)。尽管递归代码简洁,但需警惕其性能陷阱[^1][^2][^3]。 §§相关问题§§ 1. 如何优化斐波那契数列的递归解法? 2. 递归函数在栈内存中是如何存储的? 3. 尾递归优化有什么作用? </think>### 如何使用C语言实现递归函数 递归函数的本质是**函数直接或间接调用自身**,通过将大问题分解为相似的小问题来解决复杂任务。以下是实现递归函数的完整指南(参考引用[1][2][3]): --- #### 一、递归函数三要素 1. **递归出口(Base Case)** - 必须有明确的终止条件 - 例如:`if(n == 1) return 1;` - 防止无限递归导致栈溢出[^1] 2. **递归关系(Recursive Relation)** - 将问题分解为更小的子问题 - 例如:`fib(n) = fib(n-1) + fib(n-2)` 3. **参数收敛(Converging Parameter)** - 每次递归调用必须使参数向出口靠近 - 例如:每次调用`n-1`使参数递减 --- #### 二、实现步骤与示例 ##### 示例1:阶乘计算(数学定义:$n! = n \times (n-1)!$) ```c #include <stdio.h> // 递归函数实现 int factorial(int n) { // 1. 递归出口 if(n <= 1) return 1; // 2. 递归关系 + 参数收敛(n-1) return n * factorial(n-1); } int main() { printf("5! = %d", factorial(5)); // 输出120 return 0; } ``` ##### 示例2:斐波那契数列(数学定义:$F(n) = F(n-1) + F(n-2)$) ```c int fibonacci(int n) { // 双递归出口 if(n == 0) return 0; if(n == 1) return 1; return fibonacci(n-1) + fibonacci(n-2); } ``` ##### 示例3:年龄推算(引用[3]案例) ```c int age(int n) { // 递归出口:第1个人年龄 if(n == 1) return 10; // 递归关系:前一个人年龄+2 return age(n-1) + 2; } // 输出:age(5) = 18 ``` --- #### 三、内存工作原理 ```mermaid flowchart TB A[factorial(3)] -->|3*factorial(2)| B[factorial(2)] B -->|2*factorial(1)| C[factorial(1)] C -->|return 1| B B -->|return 2*1=2| A A -->|return 3*2=6| 结束 ``` 1. **调用栈建立** - 每次递归在栈中创建新帧 - 存储参数、返回地址、局部变量 2. **栈帧释放** - 遇到递归出口后逐层返回 - 栈帧按LIFO(后进先出)顺序销毁 --- #### 四、递归 vs. 迭代 | 特性 | 递归 | 迭代(循环) | |--------------|-------------------------------|-------------------------------| | **代码结构** | 简洁直观(类似数学定义)[^1] | 需手动管理循环变量 | | **内存消耗** | 栈空间$O(n)$,可能溢出 | 固定$O(1)$空间 | | **适用场景** | 树遍历、分治、回溯算法 | 线性计算、简单循环任务 | | **调试难度** | 较难(多层调用栈) | 较容易 | > 引用[2]展示了阶乘的迭代实现作为对比,两者结果相同但实现逻辑不同。 --- #### 五、注意事项(常见陷阱) 1. **缺失递归出口** ```c // 错误示例:无限递归导致栈溢出 int infinite(int n) { return n * infinite(n-1); // 无终止条件! } ``` 2. **未收敛的参数** ```c // 错误示例:参数不收敛 int divergent(int n) { if(n == 0) return 1; return divergent(n); // 参数未改变! } ``` 3. **重复计算问题** - 斐波那契数列的朴素递归有$O(2^n)$时间复杂度 - 解决方案:备忘录模式(缓存计算结果) --- #### 六、调试技巧 1. **打印递归深度** ```c int factorial(int n, int depth) { printf("Depth %d: n=%d\n", depth, n); if(n <= 1) return 1; return n * factorial(n-1, depth+1); } ``` 2. **使用调试器** - 在IDE中设置递归深度断点 - 观察调用栈变化 --- ### 总结 递归的核心在于**问题分解**: 1. 定义明确递归出口 2. 建立子问题与原问题的关系 3. 确保参数向出口收敛 4. 对于性能敏感场景,优先考虑迭代或尾递归优化(编译器支持时) > 通过引用[3]的年龄计算案例可以看出,递归通过"回推-递推"机制将多层问题转化为重复的简单操作[^2][^3]。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值