1. 程式人生 > >java基礎之遞迴呼叫

java基礎之遞迴呼叫

(一)遞迴概念

遞迴本質:程式呼叫自身的程式設計技巧叫做遞迴。

程式呼叫自身的程式設計技巧稱為遞迴( recursion)。遞迴做為一種演算法在程式設計語言中廣泛應用。 一個過程或函式在其定義或說明中有直接或間接調

自身的一種方法,它通常把一個大型複雜的問題層層轉化為一個與原問題相似的規模較小的問題來求解,遞迴策略只需少量的程式就可描述出解題過

程所需要的多次重複計算,大大地減少了程式的程式碼量。遞迴的能力在於用有限的語句來定義物件的無限集合。

遞迴的三個條件:

  1. 邊界條件
  2. 遞迴前進段
  3. 遞迴返回段

當邊界條件不滿足時,遞迴前進;當邊界條件滿足時,遞迴返回。

下面通過兩個示例程式來說明:

  1. 使用Java程式碼求5的階乘。(5的階乘=5*4*3*2*1)

    1. package org.wxp.recursion;  
    2. /** 
    3.  * 計算5的階乘(result = 5*4*3*2*1) 
    4.  * @author Champion.Wong 
    5.  *  
    6.  * 
    7.  */
    8. publicclass Test01 {  
    9.     publicstaticvoid main(String[] args) {  
    10.         System.out.println(f(5));  
    11.     }  
    12.     publicstaticint f(int n) {  
    13.         if (1 == n)   
    14.             return1;  
    15.         else
    16.             return n*f(n-1);  
    17.     }  
    18. }  



    此題中,按照遞迴的三個條件來分析:
    (1)邊界條件:階乘,乘到最後一個數,即1的時候,返回1,程式執行到底;
    (2)遞迴前進段:當前的引數不等於1的時候,繼續呼叫自身;
    (3)遞迴返回段:從最大的數開始乘,如果當前引數是5,那麼就是5*4,即5*(5-1),即n*(n-1)

  2. 使用Java程式碼求數列:1,1,2,3,5,8......第40位的數
    1. package org.wxp.recursion;  
    2. /** 
    3.  * 求數列:1,1,2,3,5,8......第40位的數
       
    4.  * @author Champion.Wong 
    5.  *  
    6.  */
    7. publicclass Test_02_Fibonacci {  
    8.     publicstaticvoid main(String[] args) {  
    9.         System.out.println(f(6));  
    10.     }  
    11.     publicstaticint f(int n ) {  
    12.         if (1== n || 2 == n)   
    13.             return1;  
    14.         else
    15.             return f(n-1) + f(n-2);  
    16.     }  
    17. }  



    此題的突破口在:從第3位數開始,本位數是前兩位數的和。要計算第多少位的值,那麼就需要將位數作為引數傳進方法進行計算。
    (1)首先,當位數為1和2時,當前返回的值應該是1;
    (2)然後,當位數為3時,返回值應該=2=1+1;
                     當位數為4時,返回值=3=2+1;
                     當位數為5時,返回值=5=3+2;
                     當位數為6時,返回值=8=5+3;
                     ......
    (3)由(2)得知,大於等於3的情況下,當前位數(n)的數值=f(n-1)+f(n-2)
(二)非遞迴方法實現(迭代方法) 迭代本質:利用變數的原值推算出變數的一個新值,迭代就是A不停的呼叫B. 通過觀察推導,找到解決問題的方法,發現其中的規律,將其轉化成程式語言表達出來。 本質:使用合適的資料型別變數代替問題中的資料,將解決問題的方法轉化為符合程式語言的邏輯。
public  class  Fab{

     public  static  void  main( String[] args){

    System.out.println(f(20));
}     

   public static long  f(int index){

       if(index == 1 || index ==  2){
              return  1;
       }

       long f1 =  1L;
       long f2 =  1L;
       long  f = 0;
 
       for(int i=0; i<index; i++){
              f = f1 + f2;
              f1 = f2;
              f2 = f;
       }
       return f;
   }

}


       遞迴其實是方便了程式設計師難為了機器,遞迴可以通過數學公式很方便的轉換為程式。其優點就是易理解,容易程式設計。但遞迴是用機制實現的,每深入一層,都要佔去一塊棧資料區域,對巢狀層數深的一些演算法,遞迴會力不從心,空間上會以記憶體崩潰而告終,而且遞迴也帶來了大量的函式呼叫,這也有許多額外的時間開銷。所以在深度大時,它的時空性就不好了。(會佔用大量的記憶體空間)
而迭代雖然效率高,執行時間只因迴圈次數增加而增加,沒什麼額外開銷,空間上也沒有什麼增加,但缺點就是不容易理解,編寫複雜問題時困難。
能不用遞迴就不用遞迴,遞迴都可以用迭代來代替。(要辯證的看待這個問題,深度不大,還是可以採用遞迴的)。