Java中尾遞歸


       在以往解決需要遞歸求解的問題上一直使用傳統遞歸,而不久前老師講解了尾遞歸感覺需要記錄一下(好記性不如爛筆頭)

       尾遞歸特點:在普通尾調用上,多出了2個特征。

       1.在尾部調用的是函數自身(Self-called)

       2.可通過優化,使得計算僅占常量棧空間(Stack Space)

       舉個例子:

       斐波那契數列(Fibonacci sequence),又稱黃金分割數列、因數學家列昂納多·斐波那契(Leonardoda 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*)在現代物理、准晶體結構、化學等領域,斐波納契數列都有直接的應用。

        下面代碼僅求斐波那契數列的第n項為多少,而不求前n項和。

         

 1 public class Fibonacci {
 2 
 3     public static void main(String[] args) {
 4         int n = 50;
 5         long begin1 = System.currentTimeMillis();
 6         System.out.printf("%d\n", fibonacci(n));
 7         long end1 = System.currentTimeMillis();
 8         System.err.println("花費時間:" + (end1 - begin1) + "毫秒");
 9         
10         long begin2 = System.currentTimeMillis();
11         System.out.printf("%d\n", advanced(n, 0L, 1L));
12         long end2 = System.currentTimeMillis();
13         System.err.println("花費時間:" + (end2 - begin2) + "毫秒");
14     }
15 
16     static long fibonacci(int n) {
17         if (n < 0)
18             return -1;
19         if (n <= 1)
20             return n;
21         return fibonacci(n - 1) + fibonacci(n - 2);
22     }
23 
24     static long advanced(int n, long ret1, long ret2) {
25         if (n < 0)
26             return -1;
27         if (n == 0)
28             return ret1;
29         if (n == 1)
30             return ret2;
31         return advanced(n - 1, ret2, ret1 + ret2);
32     }
33 
34 }

             結果顯示:

             計算fibonacci數列第50項。

             

               一些初學的想法:傳統的遞歸相當於樹狀圖計算,而尾遞歸相當於循環計算   

              譬如計算數字階乘時:假設計算8!,傳統遞歸理解為8*7*6*5*4*3*2*Factorial(1);遞歸函數中留有出口,直到遞歸到出口參數為1時才返回值。

                                                                          尾遞歸相當於循環計算,我看做為循環遞歸。計算8!就循環8次。函數形如:

 

static long advanced(int n, int r) {
        if (n < 0) {
            return -1;
        } else if (n == 0) {
            return 1 * r;
        } else {
            return advanced(n - 1, r * n);
        }
    }

 

             其中第一個參數為循環遞歸次數,第二個參數為每一步循環計算出的數,作為新的參數繼續進行遞歸。(簡單來說就是算出階乘的每一步值作為新的參數)

            函數返回自身函數,計算最終答案,進行下一函數計算時,不在依賴於上一函數,減少了棧空間的開辟。

       

           ps:感覺類似於一串數的正反相乘過程。


免責聲明!

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



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