35.【C语言】详解函数递归

目录:

定义

作用

例子1~3

拓展学习

趣味练习

1.定义:函数自己调用自己(推回

int main()
{
  main()
  return 0;
}

这样容易死循环,导致爆栈(Stack Overflow)

所以需要设立限制条件,使执行时越来越接近条件,满足限制条件时停止递归

2.作用:大事画小,小事化了(大问题变多个子问题)

3.例子1

之前写过(迭代)E5.【C语言】练习:计算n的阶乘

但不是用递归实现的

递归思路:n!=n*(n-1)!

                  5!=5*4!=5*4*3!=5*4*3*2!=5*4*3*2*1(逐渐展开化解问题)

写成伪代码:n!=n*fact(n-1)=n*(n-1)*fact(n-2)=...=n*(n-1)*(n-3)*...*1(递推到限制条件后,再回归,即代入数据计算)

特例:0!==1

思路:写一个函数fact(factorial n.阶乘)

1ed77d862a4f4324a8fac785f5c621c1.png

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int fact(int n)
{
	if (0 == n)//限制条件
		return 1;
	else
		return n * fact(n - 1);
}
int main()
{
	int n = 0;
	scanf("%d", &n);
	int a = fact(n);
	printf("%d\n", a);
}

ba2d941bbe674991aa335167a534828d.png

注意:每次调用时要向栈区申请内存空间来存放信息,该空间叫运行时堆栈或函数栈帧空间

计算完后销毁

4.例子2

之前写过E16.【C语言】练习:输入一个正的整数,逆序打印这个整数的每一位

不是用递归写的

现创建函数print

写成伪代码:print(1234)==printf("%d",4);+print(123);=printf("%d",4);+printf("%d",3");+print(12);=...

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int print(int n)
{
	if (n != 0)
	{
		printf("%d", n % 10);
		print(n / 10);
	}
}
int main()
{
	int n = 0;
	scanf("%d", &n);
    print(n);
}

如果改成:输入一个整数,正序打印(即回归时打印)该整数的每一位

输入:1234

输出:1 2 3 4

略作改动

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int print(int n)
{
	if (n > 9)
	{
		print(n / 10);
	}
	printf("%d ", n % 10);
}

int main()
{
	int n = 0;
	scanf("%d", &n);
    print(n);
}

注意:当n>9时,并不会执行下面的printf(递推),一旦达到限制条件时,会printf每一位(回归)

5.例子3

求第n个斐波那契数(介绍

这里写一个函数fbi,令fbi(0)=0; fbi(1)=1; fbi(2)=1;

核心公式是fbi(n)==fbi(n-1)+fbi(n-2)

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int fbi(int n)
{
	if (1 == n || 2 == n)
	{
		return 1;
	}
	else
	{
		return fbi(n - 1) + fbi(n - 2);
	}
}

int main()
{
	int n = 0;
	scanf("%d", &n);
    int a=fbi(n);
	printf("%d\n", a);
}

但输入较大的数字计算很慢

可以用循环实现

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int fbi(int n)
{
	int sum = 0;
	int a = 1;
	int b = 1;
	int c = 0;
	if (1 == n || 2 == n)
	{
		return 1;
	}
	else
	{
		while (sum < n - 2)
		{
			c = a + b;
			a = b;
			b = c;
			sum++;
		}
		return c;
	}
}

int main()
{
	int n = 0;
	scanf("%d", &n);
    int a=fbi(n);
	printf("%d\n", a);
}

改动后还可以打印前n个斐波那契数

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int fbi(int n)
{
	int sum = 0;
	int a = 1;
	int b = 1;
	int c = 0;
	if (1 == n)
	{
		printf("1");
	}
	else if (2 == n)
	{
		printf("1 1");
	}
	else
	{
		printf("1 1");
		while (sum < n - 2)
		{
			c = a + b;
			a = b;
			b = c;
			sum++;
			printf(" %d",c);
		}
		return c;
	}
}

int main()
{
	int n = 0;
	scanf("%d", &n);
    fbi(n);
}

6.拓展学习

*青蛙跳台阶

一共n个台阶,青蛙一次可以跳1个或2个台阶,一共有多少种跳法?

思路:可以倒推,从终点起,可以从第n-1阶跳下或第n-2阶调下

所以jump(n)=jump(n-1)+jump(n-2)

*汉诺塔

A柱有n个盘子,上小下大,现要将A柱的盘子全部移动到C盘(可以借助B柱),但要保证ABC三柱始终保持盘子上小下大且在三根柱子之间一次只能移动一个圆盘,求一共需要多少步
简单思路:仍然倒推,最终一定是n-1个盘在B柱,A柱只剩下最大的盘-->n-1=(n-2)+1 n-2个盘在B柱,A柱剩次大的盘,C柱有最大的盘-->......

7.趣味练习

 2022全国乙卷,有兴趣的可以写代码试试

点击查看答案(第E21篇)

推荐阅读:E20.【C语言】练习:函数

28.【C语言】函数系列上 库函数

29.【C语言】函数系列中 自定义函数

30.【C语言】函数系列下

  • 34
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值