九.函数的递归总结

1. 递归是什么?

递归是一种在函数中调用自身的编程技巧即函数自己调用自己

写一个史上最简单的递归:

#include <stdio.h>
int main()
{
	printf("hehe\n");
	main();//自己调用自己

	return 0;
}

1.1 递归的思想

递归的基本思想是:一个问题的解决可以通过将其分解成相同类型的子问题来实现。每个子问题都会进一步分解,直到遇到“基准情况”——即不再需要递归的情况

递归的思考方式就是把大事化小的过程

递归中的递就是递推的意思,归就是回归的意思

1.2 递归的限制条件

递归函数必须有以下两个条件:
1.递归存在限制条件,当满足这个限制条件的时候,递归便不再继续
2.每次递归调用之后越来越接近这个限制条件

2. 递归举例

2.1 举例1: 求 n 的阶乘

阶乘是一个经典的递归问题,定义为:n! = n * (n - 1)!,当 n = 0 时,0! = 1

2.1.1 分析和代码实现

阶乘的递归定义为:

#include <stdio.h>

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);

	return 0;
}
2.1.2 画图推演

Fact(5) 为例:

请添加图片描述

每一次递归调用都在等待下一次递归的返回值,直到遇到基准情况 Fact(0),然后逐步返回结果

在c语言中,每一次函数调用,都要为这次函数调用
在栈区申请一块内存空间,用来为这次函数调用存放信息
这一块空间就叫:运行时堆栈 或者 函数栈帧空间

请添加图片描述

2.2 举例2: 顺序打印一个整数的每一位

我们可以通过递归来顺序打印整数的每一位

首先,递归将整数的最后一位打印出来,然后再递归处理剩余部分

2.2.1 分析和代码实现

例如,打印 1234

void Set(int n)
{
	if (n > 9)
		Set(n / 10);

	printf("%d ", n % 10);
}

#include <stdio.h>

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

	return 0;
}
2.2.2 画图推演

Set(1234) 为例:

Set(1234)
Set(123)+ 4
Set(12)+ 3 + 4
Set(1)+ 2 + 3 + 4

递归逐步处理每一位,直到所有位都被打印出来

3. 递归与迭代

递归和迭代(循环)都可以解决相同的问题,但它们的实现方式不同。递归通过函数调用来重复执行,迭代通过循环来完成相同的任务。

举例3: 求第 n 个斐波那契数

斐波那契数列的定义为:

Fib(n) = 1                      (n <= 2)
Fib(n) = F(n-1) + F(n-2)          (n > 2)
递归实现
int count = 0;//查看计算量
int Fib(int n)
{
	if (n == 3)
		count++;
	if (n <= 2)
		return 1;
	else
		return Fib(n - 1) + Fib(n - 2);
}

#include <stdio.h>

int main()
{
	int n = 0;
	scanf("%d", &n);
	int r = Fib(n);
	printf("%d\n", r);
	printf("count = %d", count);
	return 0;
}
迭代实现
int Fib(int n)
{
	int a = 1;
	int b = 1;
	int c = 0;

	if (n <= 2)
		return 1;
	while (n > 2)
	{
		c = a + b;
		a = b;
		b = c;
		n--;
	}
	return c;
}

#include <stdio.h>

int main()
{
	int n = 0;
	scanf("%d", &n);
	int r = Fib(n);
	printf("%d\n", r);
	return 0;
}

递归 vs 迭代

  • 递归:代码简洁,但在处理较大数据时可能导致栈溢出
  • 迭代:通常更高效,不易出现栈溢出问题
递归的定义

递归是指在解决一个问题时,函数调用自身来解决子问题,直到满足某个终止条件为止。递归通常包含两个关键部分:

基本情况(Base Case):递归的终止条件
递归步骤(Recursive Case):函数调用自身来解决更小的子问题

迭代的定义

迭代是指通过循环(如for循环或while循环)反复执行某些操作,直到满足某个条件为止。每次循环通过改变某些变量来推进计算,直到达成终止条件

递归和迭代的区别

  1. 思想和执行方式:
    • 递归是通过函数自身调用来解决问题,常常涉及到堆栈的使用来保持每次函数调用的状态
    • 迭代是通过循环结构在内存中逐步计算,每次循环更新变量的状态
  2. 内存使用:
    • 递归通常需要更多的内存,因为每次函数调用都需要在栈上分配新的内存空间(递归深度大时可能会导致栈溢出
    • 迭代通常只需要固定的内存空间来存储当前的状态
  3. 代码结构:
    • 递归的代码结构通常较简洁,能够更自然地表达一些分治类问题(如树的遍历)
    • 迭代代码结构通常更长,尤其是在需要手动维护循环变量时,但它避免了递归可能带来的堆栈溢出问题
  4. 性能:
    • **递归由于函数调用的开销,通常会比迭代慢,**尤其在深度较大的情况下
    • 迭代通常更高效,尤其是对于简单的循环问题
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值