C语言函数之递归调用

提示:本文主要是掌握函数的递归


前言

函数是学习C语言的最重要知识点之一,要学好这门编程语言,那么函数当然是至关重要的。


提示:以下是本篇文章正文内容,下面案例可供参考

什么是递归

在之前的博客“函数的基本认识”中,我们已经讲述过了函数的调用,那么它究竟是怎样进行调用的呢?
函数调用其实是通过栈来实现的。在调用函数的时候,系统会给被调用的函数分配空间,这块空间被安排在一个栈里面。每调用一次函数,系统就会自动在栈顶为它分配一次空间,退出一次则该空间也会被栈顶释放。而正在运行中的函数的存储区在栈顶。
由于栈顶的原则讲究先进后出,因此在有多个函数进行嵌套调用时,会满足先调用后返回。讲到这里
很多人都应该听说过这么一个故事:

从前有座山,山里有座庙,庙里有个老和尚在讲故事讲的是:从前有座山,山里有座庙,庙里有个老和尚在讲故事讲的是从前有座山,山里有个庙…

递归也是一种函数调用,是程序调用自身的编程技巧。
简单地来说、递归就是函数自己调用自己。它是一种特殊的函数调用,递归策略只需要少量的代码就能够描述出所需要的多次重复计算。
下面我们来写一个程序来更加直观地看看函数是如何调用自己的。

# include <stdio.h>

void Hello(int n); //函数声明

int main(void)
{
	int n = 0;
	printf("你需要输出多少个你好:");
	scanf("%d", &n);
	Hello(n); //函数调用
	return 0;
}

void Hello(int n) //函数的定义
{
	if (n > 0)
	{
		printf("你好 ");
		Hello(n - 1);
	}
	else
	{
		return;
	}
}

运行结果如下:
在这里插入图片描述
其调用函数的具体过程如下:
在这里插入图片描述
从上面这个运行过程来看,自己调用自己必须要知道自己什么时候停下来,否则就会一直不停调用自己,造成所说的“死递归”,直到存放数据的栈满了,没有地方放了为止,但是这个时候你的计算机也就死机了。


递归的两个必要条件

不是所有的问题都可以用递归来解决,刚才我们已经通过过程图知道,自己调用自己必须要知道自己什么时候停下来,否则就会形成“死递归”。因此使用递归的两个必要条件之一就是:要有终止条件(最小事件的解)。
下面我们来一起看看递归的思想是怎么样的。上面的过程图其实已经能够很好地体现了递归的思想,现在我们来总结一下:
为了能够解决F(n),就要先解决F(n - 1),为了能够解决F(n - 1), 就要先解决F(n - 2),为了能够解决F(n - 2),就要先解决… … …像这样逐层分解,当最小的问题化解之后,再循环渐进返回来化解更高层次的问题。这就是递归思想------逐层分解,逐层合并。
根据递归的思想,可以清楚其最主要的就是找到递归的出口和递归的方式。我们已经知道了递归出口其实就是终止递归的条件,也就是找到最小事件的解。
而递归的方式值的是用什么方式进行函数的递归调用,也就是递归公式。
综上,我们的出递归的两个必要条件是:
(1)知道递归的方式
(2)清楚递归的终止条件(最小问题的解)


递归与迭代的关系

迭代是循环的一种方式。理论上来说所有的循环都能够采用递归算法,然而能够使用递归来解决的问题,有时候循环却不能解决。


递归函数的优缺点

优点:
递归函数的优点在于能够提高代码的可读性、简化程序的设计、易于理解,而且刚才也提到了能够使用递归来解决的问题,循环却解决不了。采用递归能够将一个复杂的事件逐层分解成简单的事件。不仅如此,采用递归还能够很好出反映事件的本质,让我们从本质上去理解。当然,我们刚开始学习递归的时候可能会觉得力不从心,那是由于我们对于递归见识还很少,因此不用担心。
缺点:
虽然刚才描述递归是那么那么地好,但是递归的缺点也是非常明显的。为什么这样说?递归它的速度相对于其它的比较慢、而且运行的效率非常的低。在使用递归来解决经典斐波那契数列问题的时候这两个缺点真的是超级明显。
在这里插入图片描述
斐波那契数列:前两个数之和等于第三个数。
按照递归的思想,那么就需要逐层化解、逐层合并。如果我们要求第50个斐波那契数,按递归思路:第50个 = 49(个) + 48(个)、49 = 48 + 47…就是上面那个图的大致步骤,这个问题采用递归,运行过程中会出现多次重复计算相同的数据。
递归对于存储空间的占用也比循环占用的多,浪费太多的空间
在这里插入图片描述
每调用一次函数,系统就会自动为这个函数安排一个空间,而递归自身多次调用自己。递归是由栈机制实现的每深入一层都要占用一块栈数据区域,而内存空间是有限的,因而有时候对于一些事件,递归就显得格外力不从心。


什么时候使用递归

1.当该事件递归和非递归都能使用,且没有明显问题时;
2.当该事件采用递归十分简单、非递归比较难,且没有明显问题时;
3.如果使用递归写起来十分简单,但又明显问题时一定不能使用递归


总结

以上就是今天要讲的内容,本文介绍了什么是函数递归,使用递归的两个必要条件,递归的优缺点以及什么时候使用递归。其实在实际的编程中,递归使用的并不多,但是也好好地学,毕竟在考试和面试中常用于考验人的逻辑推理能力。递归从问题的最终目标逐层化解、逐层合并,它是一种逆向思维。我认为,递归算法和人解决问题的方法很相似,因而要相信自己是能够学好递归的~


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

小小酥诶

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

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

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

打赏作者

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

抵扣说明:

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

余额充值