2016-02-06 12 views
5

これは私のAPコンピュータサイエンスコースのサンプルプログラムであり、その制御の流れを理解することはできません。誰かがこのプログラムのコントロールの流れを説明できますか?

public static void mystery(int n) 
{ 
    System.out.println("mystery called with n = " + n); 

    if (n == 0) 
    { 
     System.out.println("n is zero so no more recursive calls!"); 
     return; 
    } 

    mystery(n - 1); 

    System.out.println("We did it again with n = " + n); 
} 

public static void main(String[] args) 
{ 
    mystery(5); 
} 

それは、これを出力します

mystery called with n = 5 
mystery called with n = 4 
mystery called with n = 3 
mystery called with n = 2 
mystery called with n = 1 
mystery called with n = 0 
n is zero so no more recursive calls! 
We did it again with n = 1 
We did it again with n = 2 
We did it again with n = 3 
We did it again with n = 4 
We did it again with n = 5 

これまでのところ、私は再帰的な方法を理解し、どのようにそれを介して、自分自身を振り返り:

mystery(n - 1); 

しかし、私はどのようにそれができる表示されません次の5つの文を出力します。

n is zero so no more recursive calls! 

それが唯一の状態となるように論理的に、それはそうです:

We did it again with n = 0 

誰もが学生を支援し、それが何をしたかどのように出力私に説明できますか?

+0

例として、mystery(n - 1)を置き換えます。ミステリー(n--);どのようにして再びそれをしないかを見てください。 – misha130

+0

n == 0のときに印刷前に戻り、n == 0のときは何も印刷されません。nは、 == 0なので、コードは実行されて印刷されます。 – user3284549

答えて

2

'nがゼロであるため、再帰呼び出しがありません!'メソッドは継続します(状態はスタックに置かれ、メソッド(n-1)への呼び出しが終了した後にロードされます)。

4

関数が終了すると、関数を呼び出した関数は完了し、 。。ここでは

この再帰が起こるかの実例である 再帰の各レベルをインデントの増加によって示される

mystery(5): 
    "mystery called with n = 5" 
    mystery(4): 
     "mystery called with n = 4" 
     mystery(3): 
      "mystery called with n = 3" 
      mystery(2): 
       "mystery called with n = 2" 
       mystery(1): 
        "mystery called with n = 1" 
        mystery(0): 
         "mystery called with n = 0" 
         "n is zero so no more recursive calls!" 
         mystery(0) returns 
        "We did it again with n = 1" 
        end of mystery(1) 
       "We did it again with n = 2" 
       end of mystery(2) 
      "We did it again with n = 3" 
      end of mystery(3) 
     "We did it again with n = 4" 
     end of mystery(4) 
    "We did it again with n = 5" 
    end of mystery(5) 
1

ここでは、再帰的なプログラムを考えるのは良い方法です:あなたは、プログラムのコードを読むときあなたがまだそれを知らないにもかかわらず、プログラムが何をしているかを知っているふりをする。エーション、これは次のようになります。

  • n == 0場合は、印刷の固定メッセージが - それはだno more recursive calls!文字列
  • n != 0場合は、印刷に続いて印刷nn-1のためのプログラムのプリントは、nを印刷して、その後何でももう一度 - 言い換えれば、プログラムが印刷するものの周りに2つのメッセージの「フレーム」があります。n-1

ここでは、これがどのように見えるかです:

mystery called with n = <something> 
... whatever the program prints in between... 
We did it again with n = <something> 

最初のプリントアウトは、コールの再帰部分に入る前起こります。再帰部分から戻っての後に最後のプリントアウトはになります。 nの値が各スタックフレームに格納され、再帰が巻き戻されるときに以前の値に設定されるため、は上部と下部で同じです。

この画像をそのまま使用して、n==0になるまでネストされた「フレーム」を追加し続けることは容易にわかります。その時点でメッセージを途中で印刷します。

0

謎の方法で最初の5回、このメソッドは再帰呼び出しで停止しません。それは続けて、「私たちはもう一度やった」という結果を出す。しかし、私は謎がブロックされているので、最後の再帰呼び出しが返されると、メソッドは終了することしか許されないと考えます。最初の5つの呼び出しは、元の結論に進んで打つ時のn = 0だから、印刷は「我々は再びそれをやったのn = ...」

0

ここで実行は、この再帰的なメソッドが何をするかの通過です:

mystery(5): { 
| println("mystery called with n = 5"); 
| 
| n != 0: 
|  skip return 
| 
| mystery(n - 1) is mystery(4) 
| 
| call mystery(4): { 
| | println("mystery called with n = 4"); 
| | 
| | n != 0: 
| |  skip return 
| | 
| | mystery(n - 1) is mystery(3) 
| | 
| | call mystery(3): { 
| | | println("mystery called with n = 3"); 
| | | 
| | | n != 0: 
| | |  skip return 
| | | 
| | | mystery(n - 1) is mystery(2); 
| | | 
| | | call mystery(2): { 
| | | | println("mystery called with n = 2"); 
| | | | 
| | | | n != 0: 
| | | |  skip return 
| | | | 
| | | | mystery(n - 1) is mystery(1); 
| | | | 
| | | | call mystery(1): { 
| | | | | println("mystery called with n = 1"); 
| | | | | 
| | | | | n != 0: 
| | | | |  skip return 
| | | | | 
| | | | | mystery(n - 1) is mystery(0); 
| | | | | 
| | | | | call mystery(0): { 
| | | | | | println("mystery called with n = 0"); 
| | | | | | 
| | | | | | n == 0: 
| | | | | |  return from mystery(0) 
| | | | | } 
| | | | | 
| | | | | back inside mystery(1), continue executing where we left off 
| | | | | println("We did it again with n = 1") 
| | | | | method ends; return to caller 
| | | | } 
| | | | 
| | | | back inside mystery(2), continue executing where we left off 
| | | | println("We did it again with n = 2") 
| | | | method ends; return to caller 
| | | } 
| | | 
| | | back inside mystery(3), continue executing where we left off 
| | | println("We did it again with n = 3") 
| | | method ends; return to caller 
| | } 
| | 
| | back inside mystery(4), continue executing where we left off 
| | println("We did it again with n = 4") 
| | method ends; return to caller 
| } 
| 
| back inside mystery(5), continue executing where we left off 
| println("We did it again with n = 5") 
| method ends; program ends 
} 
関連する問題