9.C语言函数递归,求n的阶乘(n!)(快乐动画版)

1.递归是什么

函数自己调用自己。

2.使用递归的限制

2个限制条件:
每次递归调⽤之后越来越接近这个限制条件,当满足限制条件时,递归便停止。
看栗子:求n的阶乘,n! = n ∗ (n − 1)!
2个限制条件如下:
在这里插入图片描述
代码实现
不考虑n太大,因为会溢出(后面结尾解释为什么溢出,并且求阶乘的更好的方法是迭代不是递归)

#include <stdio.h>
int Ret(int n)
{
	if (n <= 0)
		return 1;
	else
		return Ret(n - 1) * n;
}
int main()
{
	int n = 0;
	scanf("%d", &n);
	
		int ret = Ret(n);
		printf("%d的阶乘是%d", n, ret);
	
	return 0;
}

运行结果:
在这里插入图片描述
为了更容易观察代码的变化动图里面,我将代码里面的Ret(n-1)*n的结果视觉化成num,把返回值回来时的n用 n=n 视觉化成n,这样子,可以用监视窗口观察n和num的变化

  1. 如果满足第一个限制条件,代码是怎么运行的,输入0进行调试。
    (如果不懂vs怎么调试的,可以移步我的这篇博客 http://t.csdn.cn/h8roc
    我是直接F11进行调试,随着箭头的移动,代码在一步一步进行。在这里插入图片描述

  2. 如果满足第二个限制条件,代码是怎么运行的,输入0进行调试。
    为了更容易观察代码的变化把Ret(n-1)*n的结果视觉化成num,把返回值回来时的n用 n=n 视觉化成n,这样子,可以用监视窗口观察n和num的变化
    动图描述:在这里插入图片描述

文字描述:
看到 n 输入1的时候,跳到 Ret(n-1)*n 那里时,函数开始调用自己,不断n-1,我们也可以看到n不断变化:1,0
然后再不断返回自己的值,比如调用到n=0时,return 1,然后跳到n=1时,num=(返回的1)乘(n=1),num=1,再return num,因为n=1是最初的n,所以num是直接返回主函数的Ret(n)。
画图描述:
在这里插入图片描述

这是输入2的代码递推和回归过程:
在这里插入图片描述

3.讨论n太大为什么会栈溢出?

每⼀次函数调⽤,都需要为本次函数调⽤在栈区申请⼀块内存空间,保存函数调⽤期间的局部变量的值,
这块空间被称为运⾏时堆栈,或者函数栈帧
假设我们的n是100
函数递归一直不返回,函数对应的栈帧空间就⼀直占⽤,直到函数递归不再继续,开始回归,才逐层释放栈帧空间,所以如果采⽤函数递归的⽅式完成代码,递归层次太深,就会浪费太多的栈帧空间,也可能引起栈溢出(stack over flow)的问题。
在这里插入图片描述
所以如果不想使⽤递归,通常我们用迭代(一般是循环的⽅式)

int main()
{
	int i = 0;
	int n = 1;
	scanf("%d",&n);
	int ret = 1;
	for (i = 1; i <= n; i++)
	{
		ret *= i;
	}
	return 0;
}

此时该问题的求解,迭代实现往往⽐递归实现效率更⾼。
所以我们要看问题选择解题方法,当⼀个问题⾮常复杂,难以使⽤迭代的⽅式实现时,此时递归实现的简洁性便可以补偿它所带来的运⾏时开销。
//下一章我们更新用递归解决的例子。
1.顺序打印⼀个整数的每⼀位
2.求第n个斐波那契数
3.编写一个函数实现n的k次方,使用递归实现
4.写一个递归函数DigitSum(n),输入一个非负整数,返回组成它的数字之和

  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值