递归这个词总是听说,但许多人不曾真正理解其用法与定义,今天利用喝杯茶的时间一起一起探讨下什么是递归。
一.递归简介
1.递归的定义:函数内部调用的自身函数的编程技巧称为递归(recursion)。
2.构成递归的条件:
(1). 子问题须与原始问题为同样的事,且更为简单;
(2). 不能无限制地调用本身,须有个出口,化简为非递归状况处理。
二.递归的简单示例
结运行果为:
结果为:120
这里递归调用的过程为:
递归调用 其实就是函数的调用而已,只不过这些函数均是自身罢了,记住一点:谁调用,返回谁。上面的递归调用中,刚开始一直“往下走”,知道走到了num==0,返回1,这是fun(0)函数的值,但调用fun(0)函数的是fun(1)函数,所以fun(0)函数的值1就返回给了fun(1)函数(谁调用,返回谁),同理一直返回到fun(5)函数,由于fun(5)函数在主函数中调用,所以返回给主函数一个值,这个值就是5!,这里只要把我上面画的图看懂了,就差不多理解了。
三.递归的基本原理
1.每一级的函数调用都有自己的变量。
2.每一次函数调用都会有一次返回。当程序执行到某一级递归的结尾处时,它会转移到前一级递归继续执行。程序不能直接返回到main()中的初始调用部分,而是通过递归的每一级逐步返回,即从func()的某一级递归返回到调用它的那一级。
3.递归函数中,位于递归调用前的语句和各级被调函数具有相同的执行顺序。
4.递归函数中,位于递归调用后的语句的执行顺序和各个被调函数的顺序相反。
5.虽然每一级递归都有自己的变量。但是函数代码并不会得到复制。函数代码是一系列的计算机指令。而函数调用就是从头执行相应函数的指令集,除了会每次创建变量,递归调用非常类似于一个循环语句。
6.递归函数中必须包含可以终止递归调用的语句。
四.递归的优缺点
优点:
1. 简洁
2.在树的前序,中序,后序遍历算法中,递归的实现明显要比循环简单得多。
缺点:
1.递归由于是函数调用自身,而函数调用是有时间和空间的消耗的:每一次函数调用,都需要在内存栈中分配空间以保存参数、返回地址以及临时变量,而往栈中压入数据和弹出数据都需要时间。->效率
2.递归中很多计算都是重复的,由于其本质是把一个问题分解成两个或者多个小问题,多个小问题存在相互重叠的部分,则存在重复计算,如fibonacci斐波那契数列的递归实现。->效率
3.调用栈可能会溢出,其实每一次函数调用会在内存栈中分配空间,而每个进程的栈的容量是有限的,当调用的层次太多时,就会超出栈的容量,从而导致栈溢出。->性能