尾遞迴最佳化

來源:互聯網
上載者:User

標籤:ons   結果   特定   sharp   寫法   常見   複雜   個數   尾遞迴   

尾遞迴最佳化是利用上面的第一個特點“調用同一個方法”來進行最佳化的 
尾遞迴最佳化其實包括兩個東西:1)尾遞迴的形式;2)編譯器對尾遞迴的最佳化 
尾遞迴的形式 
尾遞迴其實只是一種對遞迴的特殊寫法,這種寫法原本並不會帶來跟遞迴不一樣的影響,它只是寫法不一樣而已,寫成這樣不會有任何最佳化效果,該爆的棧和幀都還會爆 
具體不一樣在哪裡 
前面說了,遞迴的本質是某個方法調用了自身,尾遞迴這種形式就要求:某個方法調用自身這件事,一定是該方法做的最後一件事(所以當有需要傳回值的時候會是return f(n),沒有返回的話就直接是f(n)了) 
要求很簡單,就一條,但是有一些常見的誤區 
這個f(n)外不能加其他東西,因為這就不是最後一件事了,值返回來後還要再幹點其他的活,變數空間還需要保留 
比如如果有傳回值的,你不能:乘個常數 return 3f(n);乘個n return n*f(n);甚至是 f(n)+f(n-1) 
另外,使用return的尾遞迴還跟函數式編程有一點關係 
編譯器對尾遞迴的最佳化 
上面說了,你光手動寫成尾遞迴的形式,並沒有什麼卵用,要實現最佳化,還需要編譯器中加入了對尾遞迴最佳化的機制 
有了這個機制,編譯的時候,就會自動利用上面的特點一來進行最佳化 
具體是怎麼最佳化的: 
簡單說就是重複利用同一個棧幀,不僅不用釋放上一個,連下一個新的都不用開,效率非常高(有人做實驗,這個比遞推比迭代都要效率高) 
為什麼寫成尾遞迴的形式,編譯器就能最佳化了?或者說【編譯器對尾遞迴的最佳化】的一些深層思想 
說是深層思想,其實也是因為正好編譯器其實在這裡沒做什麼複雜的事,所以很簡單 
由於這兩方面的原因,尾遞迴最佳化得以實現,而且效果很好 
因為在遞迴調用自身的時候,這一層函數已經沒有要做的事情了,雖然被遞迴調用的函數是在當前的函數裡,但是他們之間的關係已經在傳參的時候了斷了,也就是這一層函數的所有變數什麼的都不會再被用到了,所以當前函數雖然沒有執行完,不能彈出棧,但它確實已經可以出棧了,這是一方面 
另一方面,正因為調用的是自身,所以需要的儲存空間是一毛一樣的,那乾脆重新重新整理這些空間給下一層利用就好了,不用銷毀再另開空間 
有人對寫成尾遞迴形式的說法是【為了告訴編譯器這塊要尾遞迴】,這種說法可能會導致誤解,因為不是只告訴編譯器就行,而是你需要做最佳化的前半部分,之後編譯器做後半部分 
所以總結:為瞭解決遞迴的開銷大問題,使用尾遞迴最佳化,具體分兩步:1)你把遞迴調用的形式寫成尾遞迴的形式;2)編譯器碰到尾遞迴,自動按照某種特定的方式進行最佳化編譯

59488871

 

斐波那契數列

 常規的斐波那契數列演算法可能是這樣的:

1234567 int fib(int n) {     if (n <= 2) {        return 1;    }    return fib(n - 1) + fib(n - 2);}

  

上面的這種遞迴計算最終的return操作是加法操作。所以不是尾遞迴。

如果用尾遞迴就是這樣的:

123456789101112131415 /** 計算第n位斐波那契數列的值   @param n 第n個數 @param acc1 第n個數 @param acc2 第n與第n+1個數的和 @return 返回斐波那契數列值 */int tailfib(int n,int acc1,int acc2) {    if (n < 2) {        return acc1;    }         return tailfib(n-1,acc2,acc1 + acc2); }

  

比如我們想計算第10位斐波那契數列的值,只需要fib(10,1,1)即可。

看一下測試效果,測試程式如下:

1234567891011121314151617 int main(int argc, const char * argv[]) {    clock_t start,finish;        start = clock();    printf("計算結果:%d\n", fib(45));    finish = clock();    printf("花費時間--------%lu\n",finish - start);          start = clock();    printf("計算結果:%d\n", tailfib(45,1,1));    finish = clock();         printf("花費時間--------%lu\n",finish - start);    return 0;     }

  

計算結果如下:

12345 計算結果:1134903170花費時間--------5540692計算結果:1134903170花費時間--------4Program ended with exit code: 0

  https://www.cnblogs.com/zhanggui/p/7722541.html

尾遞迴最佳化

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.