2017-04-06 15 views
1

私は長い間前にクラスで基本的な再帰問題を書いていましたが、どのように出力が得られるかを覚えようとしています。Javaの再帰出力は前方と後方の名前を出力する

これは、基本的に前方と後方に名前を表示します。私はそれが名前の転送方法を理解していますが、名前を後ろにどのように印刷するかはわかりません。私は何が起こっているのかを段階的に見るためにデバッグを行いましたが、名前が印刷された後にどのようにインデックスが減少しているのか理解できません。

public class CharRecursion 
{ 

public static void printName(String name, int index) 
    { 
    if(index > name.length() - 1) 
    { 
     return; 
    } 
    else 
    { 
     System.out.println(name.charAt(index)); 
     printName(name, index + 1); 
     System.out.println(name.charAt(index)); 
    } 
    } 
public static void main(String[] args) 
    { 
     printName("Brian", 0); 
    } 

} 

出力は後方部分が第二System.out.println(name.charAt(index));の文から来BriannairB

+0

2番目の 'System.out.println'を見てください。再帰が最後に達した後で呼び出されています。 –

+0

Jaroslawのコメントに加えて、 'index + 1'は' index'の値を変更しないことに注意してください。したがって、次の行には、同じ文字が印刷されます。 –

+0

ありがとうございます。私は2番目のSystem.out.printlnがそれを引き起こしていることを理解していますが、そのインデックスは文字が後ろ向きになって減少していますか?私は単純なものを逃しているに違いない。 –

答えて

2

です。再帰呼び出しが終了した後にあなたが逆の文字列で終わるように、この1が呼び出され

のみ、再帰的に、接尾辞マーカーを見て:

System.out.println(name.charAt(index) + " - "); 
    printName(name, index + 1); 
    System.out.println(name.charAt(index) + " * "); 

をあなたが得る:

B - 
r - 
i - 
a - 
n - 
n * 
a * 
i * 
r * 
B * 

実際の呼び出し順序は

です。printName(name、0)> printName(name、2)> printName(name、3)> printName(name、4)

2番目println文が、その後printName(name, 4)printName(name, 3)、などになります解決するための最初の呼び出し...と印刷の順番は次のようになります。これを理解するために

System.out.println(name.charAt(4) + " * "); 
System.out.println(name.charAt(3) + " * "); 
System.out.println(name.charAt(2) + " * "); 
System.out.println(name.charAt(1) + " * "); 
System.out.println(name.charAt(0) + " * "); 
1

の方法は、手動でそれをステップすることで、ペンと紙を使って。 何が起きているのかを理解するまでは、物理的に実際に紙の本物ので十分に強くお勧めできません。

1枚の用紙を使用して出力を記録します。

printName()の呼び出しごとに別の用紙を使用してください。

main()から開始してください。 printName("Brian", 0)が表示されたら、これは新しい用紙を開始する信号です。シートの一番上に、入力:name - "Brian", index = 0を書きます。

今、あなたはprintName()にいるので、ステップバイステップでそれを行ってください。 0"Brian".length() - 1未満であるので、あなたはelseブロックにスキップすることができます

  • System.out.println(name.charAt(index)); - ので、あなたの出力用紙に"Brian".charAt(0)の結果を記述します。B

  • printName(name, index + 1) -- since you're seeingのprintName()again, take another sheet of paper, write the inputs名= "ブライアン"、インデックス= 1 'トップ、および以前のシートの上場所これで。

このように作業を続けていくと、紙のスタックに追加され続けます。これはJavaが維持する実行スタックに直接似ています。スタックトレースに表示されるのと同じスタックです。

最終的には、index = "Brian".length() -1のポイントに到達します。 returnが表示されたら、作業中のシートを取り出して、ねじでひねり、ビンに入れてください。ランタイムはこのメソッドの呼び出しで終了しました。あなたが途中で止めた下のシートを続けます。今度は2番目のSystem.out.println(name.charAt(index));です。その文字を出力シートに書いてください。

終了すると、出力シートに「BriannairB」と書かれていることがわかります。再帰の理解を深めることができます。

各用紙はスタックフレームを表します。

  • 実行中のある瞬間に、実行に関する限り、一番上のスタックフレームだけが「可視」になります。
  • ローカル変数とパラメータは、スタックフレームに格納されます。実行中のある瞬間に、現在のスタックフレーム内のindexの値は3になります。これは、以下のスタックフレーム内のindexの値には影響しません。これは、完全に別個のストレージ部分であり、3フレームが終了してスタックからポップされるときにはまだ2になります。

あなたはこれのこつを得れば、しかし、あなたはより多くの「宣言型」レベルでそれを見ることができます。​​は何をしますか?

"B"、次にprintName("Brian", 1) "B"を出力します。

私はこの実装を理解するためにわずかに簡単だと思う:

void printName(String s) { 
     if(s.length() > 0) { 
      System.out.println(s.charAt(0)); 
      printName(s.substring(1)); 
      System.out.println(s.charAt(0)); 
     } 
    } 

ので、printName("Brian")その後Bその後、printName("rian")B書き込みます。

またはスタックが行く最も深いから行く:

printName("")は何も書き込まれません。 nnある -

したがってprintName("n")は次にnn次いでprintName("")書き込みます。

+0

OK!スタックトレースに言及したら、それをクリックし始めました。したがって、基本的に2番目のprintln文はスタックを経由して次に来るものを吐き出し、逆になります。私が正しく理解していれば。 –

+0

@BrianHogans私は、プログラムの実行がどのように進んでいるかについてのあなたの精神的なモデルはちょっと離れていると思います。 'println'文は何も「通過しません」。 JVMは、ステートメントごとにメソッドをステップ実行します。メソッド呼び出しに遭遇すると、それはスタックに追加され、そのメソッド呼び出しを処理している間は他のすべてを保留にします。メソッド呼び出しの終わりに達すると、スタックからその項目が削除され、途中で中断された箇所が実行されます。あなたが私のアドバイスに従って紙で "実行"するなら、あなたはJVMです。 – slim

+0

私は間違いなくそれを行うでしょう。私はこれを概念的に理解してから、別のものに移ります。 –

0

以下は、プログラムの実行順序です。各呼び出しの前に最初にSystem.out.println(name.charAt(index));を実行するプログラム呼び出しprintName("Brian",index)は再帰的に機能します。インデックスが5に到達すると、関数呼び出しの戻りが開始され、各戻り後に2番目のSystem.out.println(name.charAt(index));が実行されます。

関連する問題