初学者对递归的拿捏总是有些欠妥当 ,其实就是没有掌握好一个思路 .
对于递归 , 经历往往是 恍然大悟的瞬间 .
以下是自己对递归的一些心得 ,希望能帮到有需要的人 .
1 ,要不要使用递归 ?
其实 ,递归的效率在大多数情况下是不及循环的 ,所以,能使用循环的
尽量还是用循环 .但是对于一些原生的递归,比如树的遍历,还是没有必要去想循环了
.当然 ,递归永远会出现在坑人的笔试里面...
从程序的角度讲 ,如果程序涉及到了重复操作 .而且重复的没有差别
那么我们就可以使用递归,比如:
斐波纳契数列 ,阶乘 等,这些东西的特点就是存在大量重复,并且可以缩小范围到几个操作数之内.
2 ,确定递归算法和结束条件
递归算法说白了就是怎么调用自己.
结束条件就是让程序结束,不要死循环.
算法: 最常用的是使用递推关系 ,这种是非常容易掌握并且通用的.
设计递归的时候,要有意让递归向着结束的方向进行:
例1 : 阶乘的递归算法 :
计算 n!
归纳步骤:
设计算阶乘的函数是 f(n)
(1) 当 n=1 时 , f(1)=1 ;
(2) 当 n=2 时 , f(2)=2*1=2*f(1);
.
.
.
不难总结出当 n=k时 , f(k)= k*((f(k)-1));
(如果看不出来就多写几个小的数字,继续推导)
实现代码:
int f(int i) { //结束条件 if(i==1) { return 1; } //递归语句 return i*f(i-1); } int main() { int n; printf("请输入一个整数:\n"); scanf("%d",&n); printf("n的阶乘是:%d\n",f(n)); system("PAUSE"); return 0; }
我们来看一个更实际的问题:
例2: 一个楼梯有50个台阶 ,每一步可以走一个台阶,也可以走两个台阶,请问走完这个楼梯一共有多少种方法?
举个例子: 假设有3个台阶 ,则有3种走法 :(1)1-1-1 (2) 1-2 (3) 2-1
分析:这也是一个递推关系
假设走完k个台阶有 f(k)种走法
k=1时 ,f(1)=1
k=2时 ,f(2)=2
前两步的关系似乎不那么明显:是不是 f(2)=2*f(1) ?
我们继续推导:
k=3时 ,f(3)=3 从这里应该能看出 不是f(3)=3*f(2)的这种关系了.
k=4时 ,f(4)=5 现在应该很好得出关系: f(4)=f(3)+f(2) ,如果不放心,还也可以自己继续推导验证
k=n时 ,f(n) = f(n-1)+f(n-2) ;
当然,针对这个题目,还有更灵活的思考方式:
k=n时 (1)如果第一步走了1个台阶,那么剩下 n-1 个台阶,有f(n-1)种走法.
(2)如果第一步走了2个台阶,那么剩下n-2个台阶,有f(n-2)种走法.
那么有如下公式
f(1)=1;
f(2)=2;
f(n)=f(n-1)+f(n-2);
代码:
int count(int n)
{
if(n==1)
return 1 ; //递归结束条件
if(n==2)
return 2 ;//递归结束条件
else
return count(n-1)+count(n-2) ;
}
(至于到底是怎么走的,是回溯法的问题,本篇主要讨论递归,所以不赘述)
番外篇:
到底递归是TM怎么回事?为什么调啊调的就能实现功能了!
其实就是一个重复然后返回的过程
比如:
我们对5!的计算:
结束条件是 n=1 ; 表达式是: f(n)=n*f(n-1);
执行过程:
f(5)=5*f(4);
f(4)=4*f(3);
f(3)=3*f(2);
f(2)=2*f(1);
f(1)=1 ;
f(1)的返回值给f(2),那么f(2)=2*1=2 ;
f(2)的返回值给f(3),那么f(3)=3*2=6 ;
f(3)的返回值给f(4),那么f(4)=4*3=12 ;
f(4)的返回值给f(5),那么f(5)=5*4=20 ;
小菜鸟发帖,难免疏漏,欢迎指正 ~