2015-09-18 2 views
0

Может кто-нибудь объяснить, почему печатаются две последние строки? Я понимаю, что второй вызов функции установит счет после 0: Hello, значение count: 1. Итак, как только мы передадим этот аргумент 0 нашему методу, оператор , если вернет true и выйдет метод при ударе о возвращения заявления, но представляется, что программа будет в еще заявления, даже если если является истинной! Я отлаживал и видел пошаговый анализ, но все еще не понимал этого. Я думаю, что только первые две строки должны быть напечатаны, и после этого программа должна прекратиться. Кроме того, почему счетчик увеличивается в последнем заявлении println? Благодаря!Head Recursion Java

public class RecursionEx { 
    void myMethod(int counter){ 
     if(counter == 0){ //Base Case 
      return;  
     } else { 
      System.out.println("Hello, "+"value of count: "+counter); 
      myMethod(--counter); 
      System.out.println("value of count: "+counter); 
      return; 
     } 
    } 
    public static void main (String args[]){ 
     new RecursionEx().myMethod(2);; 
    } 
} 

/* 
OUTPUT: 
Hello, value of count: 2 
Hello, value of count: 1 
value of count: 0 
value of count: 1 
*/ 
+1

Локальные переменные метода хранятся в стеке. Поэтому каждый вызов метода получает свою собственную копию этих переменных. –

+0

Ваш отпечаток ужасен, это делает ваш код болезненным для чтения. Пожалуйста, исправьте это – Dici

ответ

1

Это, наверное, проще всего понять, если вы думаете, последовательно о том, что происходит:

  1. метод, называемый со значением «2» (глубина = 1)
  2. сообщение «Привет, значение подсчета: 2», напечатанной
  3. метод, называемый рекурсивно со значением «1» (глубина = 2)
  4. сообщение «Привет, значение счетчика: 1», напечатанной
  5. метод, называемый рекурсивно со значением «0 "(глубина = 3)
  6. Метод на глубине 3 возвращается, ничего не делая
  7. Метод на глубине 2 отпечатков «значение счетчика: 0»
  8. Метод на глубине 2 возвращается
  9. Метод на глубине 1 отпечатков «Значение подсчета: 1»
  10. метод на глубине 1 возвращается

каждый рекурсивный из MyMethod() происходит в рамках выполнения предыдущего вызова и вызова этого метода вызова не не продолжается до тех пор, рекурсивно называемой версии возвращается. Поэтому, когда вы вызываете myMethod (- counter), ваш текущий вызов myMethod() фактически приостанавливается и начинается новый. Как только этот новый метод завершит предыдущий, он продолжится там, где он остался со значениями для всех его локальных переменных нетронутым.

3

Вот что происходит на каждом уровне рекурсии:

myMethod(2) is called. 
    counter is 2, not 0, so the else is performed. 
    "Hello, value of count: 2" is printed. 
    counter is decremented to 1, and myMethod(1) is called. 
     counter is 1, not 0, so the else is performed. 
     "Hello, value of count: 1" is printed. 
     counter is decremented to 0, and myMethod(0) is called. 
      counter is 0, so the `return` (base case) is executed. 
     Here, counter is still 0, so "value of count: 0" is printed. 
    Here, counter is still 1, so "value of count: 1" is printed. 

Нет инкрементацию не происходит. Значение counter отличается на каждом уровне рекурсии, а декремент counter на одном уровне не влияет на значение counter на предыдущем уровне.

0
myMethod(--counter); 
System.out.println("value of count: "+counter); 

Ключом к пониманию рекурсии является то, что когда он попадает в базовый регистр, он возвращается, а затем выполняется следующая строка кода. Таким образом, здесь, когда он входит внутрь if и возвращает, поскольку счетчик равен 0, выполняется следующий оператор Print. Теперь счетчик равен 0, поэтому он печатает 0. После этого он снова возвращается из вызова myMethod (1) и пытается выполнить оператор печати. Здесь счетчик был 1, так что он печатает 1.

0

Несколько вещей, которые я хотел бы отметить, чтобы помочь ОРУ:

  • «возврат» выходит метод, но не выходит всю рекурсию. Кроме того, он не завершает программу, а только метод.
  • Когда вы вызываете myMethod (- counter), вы не только передаете декрементный счетчик myMethod(), но и фактически изменяете значение счетчика. Поэтому второй println() будет ВСЕГДА печатать значение текущего счетчика-1.
  • Когда вы вызываете myMethod (anyNumber), выполнение метода получает КОПИЮ «anyNumber». Поэтому любая модификация «anyNumber» не влияет на копию, используемую рекурсивным вызовом.

Аналогичное, но упрощенный пример

public class Main 
{ 
    public static void main(String[] args) 
    { 
     foo(2); 
    } 

    static void foo(int num) 
    { 
     if (num == 0) 
      return; 

     System.out.println("before: " + num); 

     foo(num - 1); 

     System.out.println("after: " + num); 
    } 
} 

Выход

before: 2 
before: 1 
after: 1 
after: 2 

PS. Пожалуйста, отформатируйте свой код перед публикацией.