您的位置:首页 > 其它

递归三部曲之深入理解斐波那契数列

2014-04-01 18:02 351 查看
之前看过全排列,但是总感觉有点别扭,因为那时候还不能驾驭递归中的回溯,最近做poj1011的Sticks的时候发现又要用到回溯的思想,但是有点看不明白,于是沉下心来好好的看看。发现还是有收获的。于是决定好好写写自己的想法和大家好好分享一下。

首先我们来了解一下什么是递归:

要想理解递归就得先理解递归;哈哈,这就是递归了。在c语言里面我们可以直接认为就是一个函数调用自己本身的做法,比如最简单的斐波拉契数列就可以这样写;

#include<stdio.h>
int sum,s;
int f(int n){
if(n==1||n==2){
sum= 1;
}
else{
sum=f(n-1)+f(n-2);
}
return sum;
}
int main()
{
s=0;
printf("%d",f(5));
}


上面的例子其实就是一个简单的递归了,我考虑一下它是如何调用的;

我们注意到,我们第一次调用函数时其实就是语句:

printf("%d",f(5));
也就是第一次传递的形参是5,5传递进去后发现既不是2,也不是1于是将执行语句:                         (1)

else
sum=f(n-1)+f(n-2);
这个时候实际上是发生了两次调用,分别是f(n-1),f(n-2),即f(4),f(3);                                                     (2)

接下来、会先调用f(4),f(3)必须得等f(4)中的所有语句执行完成的时候才能接着执行:

else
sum=f(n-1)+f(n-2);
接下来首先调用f(4),于是得到f(3),f(2),在这一步,肯定得先继续调用f(3)于是得到f(2)和f(1)执行:     (3)

if(n==1||n==2){
sum= 1;
}
//然后执行
return sum;
}
得到f(2)=1,f(1)=1;

然后我们回到第(3)步继续执行f(2),同样会执行:

if(n==1||n==2){
sum= 1;
}
//然后执行
return sum;
}
然后我们会得到f(2)=1;

接着调用(2)部分的f(3),分别得到f(2)=1;f(2)=1;

至此为止所有的调用都结束了,但是我们还没有得到答案是吧?其实接下来的话就是回溯了,我们之前的这些所有的状态其实都是存储在一个类似于栈的结构中,如果我们用n的值表示当前的状态的话,那么这个栈中的数值应该是:

                                                        5 4 3 2 1 2 3 2 1

正如图所示,当所有递归调用的时候就是开始回溯,栈中的元素开始出栈:

                                                          出栈的顺序想必大家都应该知道是:1 2 3 2 1 2 3 4 5

前面每一步的值都确定了,故后面的值也能够得出来了,如3(但事实栈里面储存的是f(3)=f(2)+f(1)这个语句的)出栈的时候f(3)=f(2)+f(1)而f(2)=1,f(1)=1是已经得出了的,故我们可以得到f(3)=2。。。。。

                                                                                      
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息