2017-07-13 3 views
7

ich Rekursion am Lernen und unten ist ein Beispiel, dass ich besser bin Verfolgung durch, es zu verstehenRekursion - warum Gebrauch return-Anweisung

public static void main(String []args) { 
    new TestRecursion().strRecur("abc"); 
} 

public void strRecur(String s) { 
    if(s.length() < 6) { 
     System.out.println(s); 
     strRecur(s+"*"); 
    } 
} 

Unten ist das, was ich bisher verstanden habe. - Beim ersten Aufruf an strRecur("abc") wird die Methode zum Ausführungsstapel hinzugefügt. Es gibt "abc" aus, bevor es aufgrund eines rekursiven Aufrufs mit dem Parameter "abc *" pausiert.

  • Der zweite Aufruf mit "abc *", schiebt strRecur(abc*) Verfahren auf den Stapel und druckt "abc *" zu trösten.

  • Der dritte Aufruf mit "abc **", schiebt Methode strRecur(abc**) auf den Stapel und druckt "abc **" zur Konsole.

  • Der vierte Aufruf mit "abc ***", schiebt die Methode strRecur(abc***) auf den Stack. Da die Basisbedingung erfüllt ist, wird die Methode abgeschlossen (ohne dass etwas gedruckt wird) und aus dem Stapel ausgeblendet.

  • Der dritte Aufruf mit "abc **" ist abgeschlossen und ausgeklappt. Da kein Code zur Ausführung ansteht, passiert nichts.

  • Der zweite Anruf mit "abc *" ist abgeschlossen und ausgeklappt. Da kein Code zur Ausführung ansteht, passiert nichts.

  • Der erste Aufruf mit "abc" ist abgeschlossen und ausgeklappt. Da kein Code zur Ausführung ansteht, passiert nichts.

Stack

Drucke auf der Konsole folgenden -

abc 
abc* 
abc** 

Ich glaube, ich verstehe, was hier geschieht. Nun möchte ich eine kleine Variation dieses Codes ausprobieren. Stattdessen strRecur(s+"*") zu nennen, würde ich return strRecur(s+"*")

public class TestRecursion { 

    public static void main(String []args) { 
     new TestRecursion().strRecur("abc"); 
    } 

    public String strRecur(String s) { 
     if(s.length() < 6) { 
      System.out.println(s); 
      return strRecur(s+"*"); 
     } 
     return "Outside If"; 
    } 
} 

Meine Erwartung war, zu tun, dass, sobald strRecur(abc***) herausspringt, dann ist es Ausgabe (abc ***) zum nächsten strRecur() auf dem Stapel zurückgeführt werden würde, so würde ich Siehe abc **** in der Konsole. Gleiches gilt für andere rekursive Aufrufe.

Die Ausgabe ist in diesem Fall jedoch genau so, als wenn es keine Rückgabeanweisung gibt. Mein Verständnis (was natürlich nicht korrekt ist) ergibt sich aus der rekursiven faktorielles Implementierung, wo wir etwas tun, wie

return n * fact(n-1); 

Hier fact(n-1) mit dem Rückgabewert von n aufgelöst wird, sobald die vorherige Methode auf dem Stapel vervollständigt. Warum verhält sich das Verhalten in diesem Beispiel nicht so?

+0

[Beispiel für ausführbare Version] (https://ideone.com/GTCArI) für den Fall, dass jemand geigen möchte. – Michael

+0

Nur ein kleiner Tipp: Ich fand, dass es beim Versuch, Rekursion zu verstehen, hilfreich ist, wenn Sie die Details jedes Anrufs ausdrucken. Starten Sie zum Beispiel Ihre rekursive Methode mit etwas wie 'System.err.println ("> strRecur s = "+ s);' und bevor Sie zurückgehen, tun Sie 'System.err.println (" biziclop

Antwort

8

Die Ausgabe beider Methoden erfolgt durch die println Anweisungen innerhalb der rekursiven Methode, weshalb sie in beiden Methoden identisch ist.

Der von der zweiten Methode zurückgegebene Wert wird nirgendwo gedruckt, weshalb Sie nicht angezeigt werden.

Wenn Sie das Ergebnis der zweiten Methode drucken würden, sehen Sie, dass es ist, da dies die Ausgabe des letzten rekursiven Aufrufs ist, die dann von allen anderen Methodenaufrufen zurückgegeben wird.

Wenn Sie die Ausgabe abc*** sein wollen, sollten Sie

return s; 

statt

return "Outside If"; 

Der vollständige Code wäre:

public static void main(String[] args) { 
    System.out.println(new TestRecursion().strRecur("abc")); 
} 

public String strRecur(String s) { 
    if(s.length() < 6) { 
     return strRecur(s+"*"); 
    } 
    return s; 
} 
+0

Außerdem, und ich weiß nicht, was OP-Anforderungen sind, müssen Sie möglicherweise die 6 bis 5 ändern. Sein erstes Beispiel wird nur so weit wie 'abc ** ' – Michael

0

Hier ist, wie es zu machen Rückgabewert:

public static void main(String[] args) { 
    String result = StrRecur("abc"); 
    System.out.print(result); 
} 

public static String StrRecur(String s) { 
    if(s.length() < 6) { 
     return s + "\n" + StrRecur(s+"*"); 
    } 
    return ""; 
} 

Dies tut das gleiche, aber der Nebeneffekt passiert nur in main.