2017-04-23 2 views
2

私は現在Javaで再帰を学習しています。私は練習のために少しコードを作った。再帰に関する問題 - なぜ私は逆出力を得るのか分かりません。

public class Tester{ 
    public static void main(String[] args){ 
     rec(5); 
    } 
    public static void rec(int x){ 
     if(x<=0){ 
      return; 
     }else{ 
      System.out.print(x+" "); 
      rec(x-1); 
     } 
    } 
} 
// Output: 5 4 3 2 1 

しかし、私は今rec(x-1);System.out.print(x+" ");を切り替えた場合、私は完全に別の出力、すなわち、逆取得:どのようにこれを可能にすることができます1 2 3 4 5

を?私はそのように理解しています:

私たちは整数5を持っています。 if文は適用されないので、51で減らし、x=4とすると、この方法を繰り返します(印刷が行われず、何も印刷されません)。言ったように、x=4と同じことをします。ステートメントが適用されない場合は、41で減らし、この方法を繰り返します。我々はそれがあるまで繰り返す。x=0。この場合、私たちは戻るので、これがメソッドの終わりです。私は逆の出力をどのように持っているのか全く理解していませんが、なぜ出力があるのか​​理解できません...? :■

+1

ああ...申し訳ありませんが、私は前の行を読んでいませんでした。解決策は、スタックによる再帰的な作業です!再帰関数を呼び出すと、関数の現在の状態がスタックに格納されます。関数が戻ると、現在の状態が復元され、残りの部分が実行されます。 –

答えて

2

[OK]をので、私たちは

print文まず、次に再帰呼び出し最初のケースを検討してみましょう: ドライラン:

x = 5 Prints 5 then calls rec(4) 
x = 4 Prints 4 then calls rec(3) 
x = 3 Prints 3 then calls rec(2) 
x = 2 Prints 2 then calls rec(1) 
x = 1 Prints 1 then calls rec(0) 
x = 0 Base case reached, so method returns in the following sequence-> 
rec(1) -> rec(2) -> rec(3) -> rec(4) -> rec(5) ->main() 

この場合には、再帰呼び出しの後に実行すべき多くの文がありませんでしたので、何も起こらなかったと方法は、第2のケースのために今すぐ戻って を返す開始しました: まず再帰呼び出し、その後print文 ドライ実行:

x = 5 as x is not less than equal to 0 goes to rec(4) but print statement is now pending execution. It wont happen until the recursive call returns 
x = 4 as x is not less than equal to 0 goes to rec(3) but again print is on hold 
x = 3 as x is not less than equal to 0 goes to rec(2) but still print is on hold 
x = 2 as x is not less than equal to 0 goes to rec(1) but still print is on hold 
x = 1 as x is not less than equal to 0 goes to rec(0) but still print is on hold 
x = 0 as x is now 0, rec(0) returns to rec(1) 

(1)(1 はその後、REC(2)今2 として値で実行され、保留中のprint文は、その後REC持っていたとして、今の値で実行された保留中の印刷なステートメントを持っていた今のrec 3)は現在実行中の保留中の印刷ステートメントを持っていますdの値が3の場合 rec(4)に保留中のprintステートメントがあり、現在は4 の値で実行されています。次に、rec(5)に保留中のprintステートメントがあり、値が5 で実行され、

この場合、出力は1-> 2-> 3-> 4-> 5 であり、最初の場合は5-> 4-> 3-> 2-> 1です。

これはあなたの理解を助けます:-)

2

これを試してみてください:

public class Tester{ 
    public static void main(String[] args){ 
     rec(5); 
    } 
    public static void rec(int x){ 
     if(x<=0){ 
      return; 
     }else{ 
      rec(x-1); 
      System.out.print(x+" "); 
     } 
    } 
} 

その理由は、あなたの脱出条件に到達するための最初の必要性(X == 0)してから、メソッド呼び出しに比べてリバースモードでの数字の印刷を開始:

rec(5) 
    rec(4) 
     rec(3) 
      rec(2) 
       rec(1) 
        rec(0) // We stop here 
       System.out.print('1 ') 
      System.out.print('2 ') 
     System.out.print('3 ') 
    System.out.print('4 ') 
System.out.print('5 ') 
2

出力は正しいです。

... 
System.out.print(x+" "); 
rec(x-1); 
... 

正しい出力である:5 4 3 2 1

及びケース2は次の:

... 
rec(x-1); 
System.out.print(x+" "); 
... 

正しい出力である:1 2 3 4をケース1次の

説明: 再帰関数では、各呼び出しはスタックに置かれます(したがって、先入れ先出しの順序で実行されます)。

ケース1の場合、rec(x)は最初に引数の値を出力してからrec(x-1)を呼び出します。したがって、順序はx x-1 x-2 ...になります。以下は、実行の順序である:

rec(5) 
    print 5 
    rec(4) 
     print 4 
     rec(3) 
      print 3 
      rec(2) 
       print 2 
       rec(1) 
        print 1 
        rec(0) 
         rec(0) return 
        rec(1) return 
       rec(2) return 
      rec(3) return 
     rec(4) return 
    rec(5) return 

ケース2では、rec(x)機能は、最初の引数を印刷する前にrec(x-1)を呼び出します。

これは、前述の2つのケースで得られている出力を理解するのに役立ちます。また、再帰的関数がより詳細にどのように機能するかについて説明する、次のstackoverflowの回答hereを読むことをお勧めします。

+0

ああ、私の本物の問題はキーワード "返品"だと思います。私はすでにインターネット上でこれを見てきましたが、その定義は非常に異なっていて不明ですが、私はまだその意味を理解していないようです。私はいつもそれが方法を終了するのに使用されていると思った。 – cnmesr

+1

@cnmesr:いいえ私はあなたの実行の正確な順序を教えるために私の説明でキーワードreturnを書いた。実際の問題は、再帰呼び出しの前または再帰呼び出しの後に数値を出力することです。これは出力の順序を決定します。私はあなたを混乱させたくありませんが、明示的に記述しなくても、すべての関数の最後に暗黙の復帰があります。 – kunal18