递归三部曲之深入理解斐波那契数列
2014-04-01 18:02
351 查看
之前看过全排列,但是总感觉有点别扭,因为那时候还不能驾驭递归中的回溯,最近做poj1011的Sticks的时候发现又要用到回溯的思想,但是有点看不明白,于是沉下心来好好的看看。发现还是有收获的。于是决定好好写写自己的想法和大家好好分享一下。
首先我们来了解一下什么是递归:
要想理解递归就得先理解递归;哈哈,这就是递归了。在c语言里面我们可以直接认为就是一个函数调用自己本身的做法,比如最简单的斐波拉契数列就可以这样写;
上面的例子其实就是一个简单的递归了,我考虑一下它是如何调用的;
我们注意到,我们第一次调用函数时其实就是语句:
接下来、会先调用f(4),f(3)必须得等f(4)中的所有语句执行完成的时候才能接着执行:
然后我们回到第(3)步继续执行f(2),同样会执行:
接着调用(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。。。。。
首先我们来了解一下什么是递归:
要想理解递归就得先理解递归;哈哈,这就是递归了。在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。。。。。
相关文章推荐
- 递归三部曲之深入理解八皇后问题
- 递归三部曲之深入理解全排列
- 深入理解javascript事件处理函数绑定三部曲(二)——传统处理函数绑定模型
- 深入理解Python中的模块、包、递归和正则表达式
- C++ Using recursion to process linked list, 深入理解递归的过程(part2)
- 深入理解递归(一)
- 深入理解递归
- 通过河内之塔问题深入理解递归思想
- 深入理解递归
- 深入理解递归
- 【算法-分治】从数组中取出n个元素的所有组合(需要深入理解递归)
- 递归关于内存的深入理解
- 3. 深入理解递归
- 深入理解递归
- java 递归深入理解
- 深入理解递归:全排列问题
- 【原创翻译】深入理解javascript事件处理函数绑定三部曲(一)——早期的事件处理函数
- 【原创翻译】深入理解javascript事件处理函数绑定三部曲(二)——传统处理函数绑定模型
- 深入理解递归(二)
- 深入理解递归