前言
递归的学习是一个漫长且需要大量练习的过程,在开始学习时,我们一定要有宏观抽象的思维。
一.什么是递归
递归算法就是一种直接或间接调用自身的算法。它通常把一个大型复杂的问题层层转化为一个与原问题相似的规模较小的问题,在逐步求解小问题后,再返回(回溯)得到大问题的解。
简单的说,就是有去有回。
二.递归使用的两个必要条件
-
存在递归出口(即算法可解的最小规模问题)。
-
每次在递归调用之后,问题规模在不断缩小。
三.递归与栈的关系
递归处理问题的顺序是:先开始处理的问题,最后才能结束处理。
栈是先进后出。
每调用一次递归,就会在栈上开辟相对应的空间,形成该函数所对应的栈帧,调用结束时,栈帧也会相应释放。
拿n的阶乘为例:
int Factorial(int n){
if (n == 0) return 1;
return
n * Factorial(n - 1);
}
常常听到 “递归的过程就是出入栈的过程”,这句话怎么理解?我们以上述代码为例,取 n=3,则过程如下:
第1~4 步,都是入栈过程,Factorial(3)调用了Factorial(2),Factorial(2)又接着调用Factorial(1),直到Factorial(0);
第 5 步,因 0 是递归结束条件,故不再入栈,此时栈高度为 4,即为我们平时所说的递归深度;
第 6~9 步,Factorial(0)做完,出栈,而Factorial(0)做完意味着Factorial(1)也做完,同样进行出栈,重复下去,直到所有的都出栈完毕,递归结束
四,递归实例
- 接受一个整型值,按照顺序打印它的每一位。
void PrintData(int n)
{
if (n > 9)
{
PrintData(n / 10);
}
printf("%d ", n % 10);
}
2.求n的k次方
int Power(int n,int k)
{
if (n == 1 || k == 0)
return 1;
return n*Power(n, k - 1);
}
- 求第n个斐波那契数。(不考虑溢出)。
int fac(int n)
{
if (n == 1 || n == 2)
return 1;
return fac(n - 1) + fac(n - 2);
}
五.递归优缺点
优点:递归算法只需少量的步骤就可描述出解题过程所需要的多次重复计算,大大地减少了算法的代码量。
缺点:如果递归的次数过多,程序中的数据过大,在不断压栈过程中会造成栈空间耗尽而产生栈溢出。
六.总结
迭代和递归是可以相互转化的,许多问题迭代的效率是高于递归的,但当一个问题相当复杂时,递归实现会更简洁。