1.递归是什么
递归是学习C语言无法绕开的一个问题,那我们就会产生问题,什么是递归?递归的作用是什么?递归可在给我们编写程序时提供什么便利?
递归其实就是解决问题的一种方法,在C语言中,递归就是函数自己调用自己。
举例一个最简单的的递归代码:
上述代码只是为了做一个示例,为了演示递归的基本形式,并不是为了解决实际的问题,代码最终会陷入死循环,从而导致栈溢出(Stack overflow)。
1.1 递归的思想
把一个大型问题层层转化为一个与原问题相似,但规模较小的子问题来求解;直到子问题不能再被拆分,递归就结束了。所以递归的思考方式就是把大事化小的过程。
通俗的理解就是,递归中的递是递推的意思,归就是回归的意思,接下来慢慢体会。
该图出自于A_caim_rhino。便于诸君理解。
1.2递归的限制条件
递归在书写的时候,有连个必要的条件:
一,递归存在限制条件,当满足这个限制条件的时候,递归便不再继续。
二,每次递归调用之后越来越接近这个条件。
2.递归举例
2.1举例1:求n的阶乘
2.1.1分析和代码的实现
n的阶乘公式:n! = n *(n - 1)!
例如:5! = 5 * 4 * 3 * 2 * 1
4! = 4 * 3 * 2 * 1
所以:5! = 5 * 4!
从这个公式不难看出:如何把一个较大的问题,转换为一个与原问题相似,但规模较小的问题来求解的。
n的阶乘和n - 1的阶乘是1相类似的问题,但是规模上要少了n。但是有一种特殊的情况是:当 n == 0的阶乘是1,而其余n的阶乘都是可以通过上面的公式计算。
这样就能写出n的阶乘的递归公式如下:
那我们就可以写出Fact求n的阶乘,假设Fact(n)就是求n的阶乘,那么Fact(n-1)就是求n-1的阶乘,函数如下:
2.1.2 画图推演
基于上述的讲解,我想诸君对递归已经有了一个比较清晰的理解。
3.递归与迭代
递归是一种很好的编程技巧,但是和很多技巧一样,也有可能被误用的,就像举例1一样,看到
推导的公式,很容易就会被写成递归的形式:
Fact函数是可以产生正确的结果,但是在递归函数调用的过程中涉及一些运行时的开销。
所以如果不想使用递归,就得想其他的办法,通常就是迭代的方式(通常就是循环的方式)。
比如:计算n的阶乘,也是可以产生1~n的数字累积乘在一起。
上述代码是能够完成任务,并且效率是比递归的方式更好的。
事实上,我们看到的许多问题是以递归的形式进行解释的,这只是因为它比非递归形式更加的清晰,但是这些问题的迭代实现往往比递归形式实现效率更高。
当一个问题非常复杂,难以使用迭代的方式实现时,此时递归的简洁性便可以补偿它所带来的运行时的开销。
举例2:求第n个斐波那契数
我们举出更加极端的例子,就像计算出第n个斐波那契数,是不适合使用递归求解的,但是斐波那契数的问题通过使用递归的形式描述,如下:
我们将代码写成递归的形式,如下所示:
当我们n如果输入更大的数字时,比如50,60等等,需要很长的时间才能得出结果, 这个计算所花费的时间,是我们很难接受的,这也说明了递归的写法是非常低效的,那是为什么呢?
其实递归程序会不断展开,在展开的过程中,我们很容易发现,在递归的过程中计算,会有重复的计算,而且递归层次越深,冗余的计算就会越多。
所以我们就需要用到迭代的方式进行计算。
迭代的方式去实现这个代码,效率就要高出很多了。但也要适可而止,而不是什么问题都要用迭代的方式去解决。
小结
递归与迭代的探究还需诸君亲身共性,需得实践出真知,如果诸君喜欢这篇blog,还请点点赞,转转发,本人定铭感五内。谢谢大家
标签:函数,递归,代码,知识,问题,阶乘,迭代,Fact From: https://blog.csdn.net/2401_87194328/article/details/143279244