0
点赞
收藏
分享

微信扫一扫

【C语言】函数的系统化精讲(三)

文章目录

  • 一、递归举例
  • 二、递归举例
    • 2.1求n的阶乘
    • 2.2 顺序打印⼀个整数的每⼀位
  • 三、递归与迭代
    • 3.1递归的思考
    • 3.2求第n个斐波那契数
  • 总结


一、递归举例

.通过上回(【C语言】函数的系统化精讲(二))我们了解到递归的限制条件,递归在书写的时候,有2个必要条件:
递归在书写时有两个必要条件:
• 递归必须有一个限制条件,当满足该条件时,递归停止。
• 每次递归调用后,逼近该限制条件。
下面我们来进行递归举例,更加深刻了解一下吧!

二、递归举例

2.1求n的阶乘

计算n的阶乘(不考虑溢出),n的阶乘就是1~n的数字累积相乘。
分析:
我们知道n的阶乘的公式: n! = n ∗ (n − 1)!

在这里插入图片描述
再稍微分析⼀下,当 n<=0 的时候,n的阶乘是1,其余n的阶乘都是可以通过上述公式计算。
n的阶乘的递归公式如下:

代码:

int Fact(int n)
{
	if (n <= 0)
		return 1;
	else
		return n * Fact(n - 1);
}
int main()
{
	int n = 0;
	scanf("%d", &n);
	int ret = Fact(n);
	printf("%d\n", ret);
	return 0;
}

在这里插入图片描述

在这里插入图片描述
当然,这里n的值不考虑太大的情况,n太大,会导致栈溢出,

2.2 顺序打印⼀个整数的每⼀位

输⼊⼀个整数m,打印这个按照顺序打印整数的每⼀位。
⽐如:
输⼊:1024 输出:1 0 2 4
输⼊:520 输出:5 2 0
分析:

Print(1024)
   |
   └── Print(102)
             |
             └── Print(10)
                       |
                       └── Print(1)
                                 |
                                 └── Print(0)
  1. 调用Print(1024)。
  2. Print(1024)调用Print(102)。
  3. Print(102)调用Print(10)。
  4. Print(10)调用Print(1)。
  5. Print(1)调用Print(0)。
  6. Print(0)直接返回,不做任何处理。
  7. Print(1)返回,打印出1,然后返回到调用它的函数。
  8. Print(10)返回,打印出0,然后返回到调用它的函数。
  9. Print(102)返回,打印出2,然后返回到调用它的函数。
  10. Print(1024)返回,打印出1,然后函数执行结束。
    11代码:
# define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>

void Print(int n)
{
	if (n > 9)
	{
		Print(n / 10);
	}
	printf("%d ", n % 10);
}
int main()
{
	int m = 0;
	scanf("%d", &m);
	Print(m);
	return 0;
}

在这里插入图片描述

三、递归与迭代

3.1递归的思考

递归是一种有用的编程技巧,但像其他技巧一样,也容易被误用。举例来说,看到推导的公式,很容易就被写成递归的形式犹如数学函数一样。
在这里插入图片描述

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

所以如果不想使用递归就得想其他的办法,通常就是迭代的方式(通常就是循环的方式)。
⽐如:计算n的阶乘,也是可以产⽣1~n的数字累计乘在⼀起的。

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

3.2求第n个斐波那契数

我们还可以举出更极端的例子,比如计算第n个斐波那契数,不适合使用递归求解,但是斐波那契数的问题通常是用递归的形式描述的,如下:
在这里插入图片描述
看到这公式,很容易想到这还不简单啊,将代码递归的形式走起,如:

int Fib(int n)
{
 	if(n<=2)
 	return 1;
 	else
 	return Fib(n-1)+Fib(n-2);
}

这里我们发现,在计算第40个斐波那契数时,使用递归方式会导致第3个斐波那契数被重复计算了39088169次,这些计算是非常冗余的。因此,斐波那契数的计算采用递归是非常不明智的,我们应该考虑使用迭代的方式来解决。
我们知道斐波那契数的前2个数都是1,然后前2个数相加就是第3个数,那么我们从前往后,从小到大计算就可以了。

这样就有下⾯的代码
int Fib(int n)
{
	int a = 1;
	int b = 1;
	int c = 1;
	while (n > 2)
	{
		c = a + b;
		a = b;
		b = c;
		n--;
	}
	return c;
}

总结

递归虽好,但是也会引⼊⼀些问题,所以我们⼀定不要迷恋递归,适当就好。
递归和循环的选择:
1,如果使用递归写代码,非常容易,写出的代码没问题,那就使用递归。
2,如果递归写出的问题,是存在明显的缺陷,那就不能使用递归,得用迭代的方式处理。

举报

相关推荐

0 条评论