递归算法算法的主要思想:把问题转化为缩小了的同类问题的子问题,然后递归调用函数(或过程)来表示问题的解。
递归算法:在函数或者过程的内部,直接或间接地调用自己的算法。
递归算法的特点
- 递归就是在过程或函数里调用自身
- 在使用递归策略时,必须要有一个明确的递归结束条件,成为递归出口
- 递归算法解题通常显得很简洁,但递归解题的运行效率低,所以一般不提倡使用递归算法设计程序
- 在递归调用的过程中系统每一层的返回点、局部变量等开辟了栈来存储。递归次数过多容易造成栈溢出,所以一般不提倡采用递归算法来设计程序。
递归算法的要求:
1.递归算法一般要求每次调用规模都有缩减(通常是减半)
2.相邻两次重复之间有紧密的联系,前一次要为后一次做准备(通常前一次的输出就作为后一次的输入)
3.在问题的规模极小时必须要求有结束条件,退出递归,否则会造成死循环,不能正常的结束
递归算法实例
求某个数的阶乘 n!=n*(n-1)* (n-2) *…*1
```
/// <summary>
/// 求n的阶乘
/// </summary>
public int Fac(int n)
{
if(n==1)
return 1;
else
return n*Fac(n-1);
}
```
经典斐波拉契数列题:一对小兔子一年后长成大兔子,一对大兔子每半年生一对小兔子,假定第一年年初投放的一对兔子,请编程实现到N年末共有多少对兔子。(设定所有的兔子都不死,一对兔子一定有且只生下一对兔子)
思路:将长到半年的兔子归为中兔子,以半年为单位来总结规律
半年数 | 0 | 1 | 2 | 3 | 4 | 5 | 6 |
---|---|---|---|---|---|---|---|
大兔子 | 0 | 0 | 1 | 1 | 1 | 2 | 3 |
中兔子 | 0 | 1 | 0 | 0 | 1 | 1 | 1 |
小兔子 | 1 | 0 | 0 | 1 | 1 | 1 | 2 |
大兔子数:前半年大兔子数+中兔子数
中兔子数:前半年小兔子数
小兔子数:前一年的大兔子数
```
/// <summary>
/// 求某个半年期的兔子数
/// </summary>
/// <param name="halfYear">半年期</param>
/// <param name="bigR">大兔子数</param>
/// <param name="midR">中兔子数</param>
/// <param name="smallR">小兔子数</param>
public void Bubbit(int halfYear,ref int bigR,ref int midR,ref int smallR)
{
if(halfYear==0)
{
bigR=0;
midR=0;
smallR=1;
}
else
{
//计算前半年的兔子数
Bubbit(halfYear-1,ref bigR,ref midR,ref smallR);
int temp=bigR;//前半年大兔子数
bigR+=midR;//大兔子=前半年大兔子数+中兔子数
midR=smallR;//中兔=前半年小兔子
smallR=temp;//小兔子=前一年大兔子数
}
}
```
递归思路:
1、明确确定的方法的功能含义
2、明确方法出口
3、符合要求时调用自身