c語言-Fibonacci數列的遞歸實現


Fibonacci數列遞歸的實現

  • 先來一個fibonacci數列的定義:
    Fibonacci數列指的是這樣一個數列:1、1、2、3、5、8、13、21、34、……在數學上,斐波那契數列以如下被以遞推的方法定義:F(1)=1,F(2)=1, F(n)=F(n - 1)+F(n - 2)(n ≥ 3,n ∈ N* 。
    Fibonacci數列在程序中的實現還是很容易,他是一個典型的可以用遞歸現實的算法。
  • 我們先來一個普通的遞歸寫法:
int fibo(int n)
{
        if(n == 1 || n == 2)
                return 1;
        return fibo(n-1)+fibo(n-2);

}
int main()
{
        int n,result;
        printf("請輸入:");
        scanf("%d",&n);
        result = fibo(n);
        printf("%d\n",result);
}

遞歸代碼簡潔,但是如果不做一定的優化,很容易出現棧溢出。以上的實現就會非常耗費內存,因為當n>2時,fibo函數需要調用自身n-2次才開始有返回值,然后開逐個返回原函數並開始計算。如果要求的n值非常大的話,可能需要同時保存成千上百個調用記錄,很容易發生"棧溢出"錯誤(stack overflow)。

  • 但是我們可以對以上實現做一個小優化-尾遞歸
    尾遞歸顧名思義-在尾部遞歸,也就是在函數執行的最后一步調用函數自身,並且,最后一步不能包含表達式。這樣,編譯器或者解釋器就可以把尾遞歸做優化,使遞歸本身無論調用多少次,都只占用一個棧幀,不會出現棧溢出的情況。

一般來說,由於只存在一個調用記錄,所以永遠不會發生"棧溢出"錯誤。

return是用來結束執行函數、並返回結果的語句,常用來做尾遞歸使用。例如:上述的 return fibo(n-1)+fibo(n-2);運算符,最后一步包含了表達式;如果把號及后面函數調用去掉,只保留 return fibo(n-1); 則為尾遞歸,但這樣達不到想要的結果,所以下面就需要一些小改動。

優化后的遞歸函數:

int fibo(int n,int i,int j)
{
        if(n ==1 || n ==2)
                return j;
        return fibo(n-1,j,j+i);
}

int main()
{
        int n,result;
        printf("請輸入:");
        scanf("%d",&n);
        result = fibo(n,1,1);
        printf("%d\n",result);
}

這樣一來,當fibo函數調用自身,就開始有return值,在遞歸結束后不用再把return值逐個返回原函數。尾遞歸的實現方式,編譯器可以幫我們節省大量的內存消耗,媽媽再也不用我的棧溢出了!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM