C语言 X 递归

递归是什么?

递归就是程序自身地调用自己,也是一种算法,递归式将一个大型复杂发问题转化为类似的小型问题。而且用的代码量较少,主要思考方式在于把大事化小。
递归的应用场景很多,在有子类的情况下都可以用递归。以后的二叉树,红黑树,也都会用到递归。

递归的条件

递归有两个必要条件。
第一个必要条件:存在限制条件,当满足这个限制条件的时候,递归便不再继续。
第二个必要条件:每次递归之后,都会越来越解决这个限制条件。

递归实例练习

在使用递归的时候,如果没思路的话,可以使用编译器的调试功能或者画图来解决。

使用递归打印应该无符号数的每一位,比如 1234 ,输出 1 2 3 4 。

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

因为递归是函数自己调用自己,所以写的时候就要把函数写在程序当中,因为这道题是输出每一位,所以就是先输出 1 然后 2 然后 3 然后 4 。画图来看:
在这里插入图片描述
上面的图片就是整个递归的所有过程,因为递归就是递下去,归回来。所以我们只要确定好限制条件和判断条件就可以这样画图来完成。

练习二:不创建临时变量,求字符串长度。

int my_strlen(char* s)		//这样是接收的第一个字符的地址
{
	if (*s != '\0')
	{
		return 1 + my_strlen(s + 1);
	}
	else
	{
		return 0;
	}
}
int main()
{
	char arr[] = "abc";
	int ret = my_strlen(arr);
	printf("%d\n", ret);
	return 0;
}

这道题的主要判断点就是有一个字符不为0,就+1,所以用字符是否为 ‘\0’ 来判断递归是否结束就可以了。所以每次递下去返回的时候就 +1 ,这样就完成了对字符串长度的统计。不过要注意的是,数组名就是首元素地址,所以用指针来接收就能一步一步指向下一个字符。指针 +1 就是指向下一个下标。当然不用指针接收也可以,写成 char s[] 也可以的。

练习三:求 n 的阶乘

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

因为求阶乘的话,最小值是1,如果是 0 的话,最后的结果就是 0 了,所以设置条件,当 n<=1 的时候,就返回 1 。当 n 大于 1 的时候,就递归下去,每次为 n * (n-1) 。

练习四:经典递归问题之斐波那契数列

我们要知道的是,斐波那契数列数列的第 n 项等于前两项的和。第一第二项等于 1 。所以先写出斐波那契数列的前几项 1 1 2 3 5 8 13 21 … 然后来写递归就好了。

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

这里就发现了每次递归的时候,都会产生很多数据,就像计算第50个斐波那契数列就会产生49 48 然后继续递归产生数据 。所以会重复计算,浪费大量时间。所以我们就可以考虑使用循环来算。代码如下:

int Fib(n)
{
	int a = 1;
	int b = 1;
	int c = 1;
	while (n > 2)
	{
		c = a + b;
		a = b;
		b = c;
		n--;
	}
	return c;
}
int main()
{
	int fib = 0;
	scanf("%d", &fib);
	int ret = Fib(fib);
	printf("%d\n", ret);
	return 0;
}

这里通过循环来算的话,效率就会很高。因为省去了递归那样的重复计算的时间。所以就可以知道什么时候用递归。

什么时候用递归

1 当解决一个问题递归和非递归都可以使用,且递归没有明显问题,那就可以使用递归。
2 当解决一个问题递归写起来很简单,非递归比较复杂,且递归没有明显问题,那就可以使用递归。
3 如果说用递归解决问题,写起来简单,但是有明显问题,那就不能使用递归。
递归不能解决问题的话,非递归再难也要写。

  • 9
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Lockey-s

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值