2017-07-30 99 views
0

所以我正在學習如何利用Java遞歸。我寫了一個簡單的程序,它添加了1和n之間的所有數字,並且它看起來是工作。在我感到困惑的地方是print語句,它打印4次(對於解決方案的每個較小部分的每個結果),如果再次調用方法並且條件尚未滿足,我很困惑它是如何到達打印語句的。我知道這可以通過在main方法中創建一個int變量並將返回值分配給它來繞開。遞歸方法打印4次

public static void main(String[] args) { 

    int sum = recursiveCall(5); 
} 

public static int recursiveCall(int num) { 

    int sum = 0; 

    if(num == 1) { 

     sum = 1; 
     System.out.println(sum); 
     return sum; 
    } 
    else { 

     sum = recursiveCall(num - 1) + num; 
    } 

    // Notice it prints out all results of sum, not just the final value. 
    System.out.println(sum); 

    return sum; 
} 
+0

通過在主方法 –

+0

中創建一個int變量可以避免遞歸打印,假設在else塊中調用'recursiveCall()'方法之後,除了'num == 1之外,它會打印4次'sum' '並從方法中返回。 –

回答

1

我畫了一個序列圖,希望這可以解釋遞歸過程。

有一個遞歸回顧過程,在調用遞歸方法之前,下一個命令將被推入調用堆棧。 所以我們可以簡單的說System.out.println會在recursiveCall之前被推送到調用堆棧,然後在recursiveCall之後返回,主進程會繼續用棧頂命令,即System.out.println

The Process of Recursion

1

讓我來解釋爲什麼會發生這種情況。

你的第二個print語句打印所有除了當n = 1。當n = 1的第一個打印語句將打印出來的值

想一想這樣的和值:每一個非空的方法調用會返回。如果它不返回,它將繼續執行,直到達到返回語句。

你說第二個打印語句應該只打印最後的總和值。但是,您會發現,該方法只能返回兩個地方 - if (num == 1)聲明或方法的末尾。當n爲1時,前一個位置只能達到一次,這意味着該方法的另外四次將通過最後的return語句返回。要在最後達到退貨聲明,必須執行第二次打印。這意味着第二個打印語句必須執行四次!

使用調試器逐步執行代碼。這是最容易理解實際發生的事情。

+0

我明白你的意思了。這實際上很有意義並且非常有幫助。乾杯朋友! –

0

這是因爲下面的其他打印語句。 在執行時遞歸函數被調用,它不會到達底部的print語句 。但是在n = 1之後,即if條件被執行,然後它返回到函數遞歸(2-1)並且返回下來並且返回sum(也是打印)並且將sum的值返回到遞歸(3- 1)被調用等等。這是它打印每個總和的地方。

僅打印最終總和的代碼如下所示。打印僅包含在主要打印最終答案中 我希望這會有所幫助。

public class add { 

    public static void main(String[] args) { 

     int sum = recursiveCall(5); 
     System.out.println(sum); // this will print 15 
    } 

    public static int recursiveCall(int num) { 

     int sum = 0; 

     if(num == 1) { 

      sum = 1; 
      //System.out.println(sum); this will print 1 
      return sum; 
     } 
     else { 

      sum = recursiveCall(num - 1) + num; 
     } 
     // System.out.println(sum); //this is the reason for each sum. 
     return sum; 

    } 

} 
0

當遞歸堆棧已滿,然後開始從尾排空本身。這就是您的if語句下面的print語句開始執行的原因。注意:遞歸進程將返回其被調用的值,所以如果條件不滿足,它將返回到該點,但是整個遞歸過程將繼續進行,直到棧被清空。無論我說什麼都叫做尾遞歸。

+0

這不是尾遞歸。 https://softwareengineering.stackexchange.com/questions/272061/why-doesnt-java-have-optimization-for-tail-recursion-at-all –