从fibonacci数列浅谈递归

来源:互联网 发布:海口优化公司 编辑:程序博客网 时间:2024/05/21 10:41
   递归(the repeated application of a recursive procedure or definition.--摘自维基百科)重复调用的过程。
使用递归法来构造fibonacci数列应该是十分简明易得的,如下:
   int Fibonacci(int n){//假设fibonacci数列从f(0)开始;
     if(n==0 || n==1){
    return 1;
    }else{
        return Fibonacci(n-1)+Fibonacci(n-2);//递归调用 :容易导致栈溢出
    }
}
  正如我在这段代码注释一样,递归调用最大的问题也就是栈深的问题。在我的笔记本上,当n>200时,需要快一分钟时间才能计算出来。所以,你看到,当递归量加大,不仅影响栈空间,而且增加时间的计算,其中不乏同一个量的持续计算;采用递归方法,fibonacci数列的时间复杂度为O(2^n),这是难以忍受的。
再看fibonacci数列,我们可以列举几个fibonacci数看一看求解过程;
F(1)=1;F(0)=1;
f(2)=f(1)+f(0)=2;
f(3)=f(1)+f(2)=f(0)+(1)+f(1);
  不知道你是否看到重复计算的过程,当n=4时,采取递归时,f(1)重复计算了一次,但是f(2)在之前的计算中已经得出结果,所以如果可以采取一个数据量或者采取某种数据结构来储存fibonacci数列之前产生的数,则可以提高时间效率;这就是迭代法解决fibonacci数的核心;
如下,采取迭代法的代码:
int Fibonacci(int n) {   //迭代调用
        int current,pre,last;
        pre=0;last=1;


        if(n==0){
            return 0;
        }else if(n==1){
            return 1;
        }
        else{
            for(int i=2;i<=n;i++){
                current=pre+last;
                pre=last;
                last=current;
            }
            return current;
        }


    }
所以你看到该迭代将fibonacci数列的复杂度减少到O(n);


  受此启发,我们是否可以就在递归的过程中实现类似迭代的过程,及通过减少递归的项数,增加每一层递归的中间数;尾递归就是此方面的代表:
< a subroutine call performed as the final action of a procedure>
如下是尾递归的代码:
int fiboTail(int n, int a, int b)//尾递归
{
  if (n == 0) return a;
  if (n == 1) return b;
  return fiboTail(n - 1, b, a + b);
}
你看到如此简洁,如递归那般简洁的代码,却有着递归难以企及的复杂度优化,核心是通过a,b来构造中间数,易得它的复杂度也是O(n);
0 0
原创粉丝点击