递归
递归是一种重要的方法,这不是一种算法,像循环和选择一样是组成算法的一个部分。
简单来说递归就是一个函数调用了自己。
例如
void f(){
f();
}
函数出口
当一个进程调用函数时,当前进程就会暂停,进而去运行被调用函数,知道被调用函数结束,则继续运行当前进程。
所以如果简单的调用自己,那么这个被调用的“自己会继续去调用“自己””,所嵌套的进程越来越多,这是一个死循环,这是我们不想看到的。
为了防止这种情况发生,递归函数一定会设置一个函数出口,用于结束某一层的递归,出口的设置取决于算法思路。
例如
void f(int a){
if(a<0)return;
f(a-1);
}
递归在算法中的作用
简单来说递归可以将算法中的大问题拆解为许多具有递归性质的小问题解决。
何为递归性质?大问题拆解为小问题的方法与小问题拆解为更小问题的方法一致。
典型的递归应用
(1)递归表达式推导出的问题,例如斐波那契数列,杨辉三角,阶乘……
(2)递归方法解决的问题,例如汉诺塔问题,这类问题只能通过递归解决……
(3)具有递归性质的数据结构的问题,例如:二叉树(子树是递归性的),链表(后继是递归性的)
递归与循环
递归与循环是解决问题的两种方法,递归通常浅显的描述了问题的解决方法,使得程序非常易懂,也是最好想到的问题解决方法;循环是对一个步骤的重复操作,解决问题往往不会清晰的看到问题的解决方法。
递归与循环并无优劣之分,各有优势也各有劣势。
递归虽然简单但是往往需要消耗大量内存,因为每一次进行函数调用都需要暂停当前进程,开启一个新的进程,大量的函数嵌套会大大增加运行成本。(一般编程软件都要求递归进程不能超过100层)
所以在一些时间复杂度的限制,我们会将递归转化为循环解决(基本所有的递归都可以用循环解决),这需要循环与栈堆的结合运用。