Почему эта рекурсивная функция Java не работает должным образом? - PullRequest
2 голосов
/ 18 февраля 2012
public class cash
{
    public void test(int a)
    {
        if(a<5)
        {
            System.out.print(a+" ");
            test(++a);
            System.out.println(a);
        }
        System.out.println("fin");
    }
    public static void main(String[] argsc)
    {
        cash c=new cash();       
        c.test(1);
    }
}

Выход:

1 2 3 4 fin
5
fin
4
fin
3
fin
2
fin

почему? Я думаю, что выход должен быть 1 2 3 4 фин. большое спасибо.

Ответы [ 9 ]

4 голосов
/ 18 февраля 2012

Хорошо, это ваш рекурсивный метод:

public void test(int a)
{
    if(a<5)
    {
        System.out.print(a+" ");
        test(++a);
        System.out.println(a);
    }
    System.out.println("fin");
}

каждый оператор в этом методе вызывается при его вызове. давайте подумаем о семантике в этом методе. Этот список на словах описывает, что делает ваш метод:

  • проверьте, если
    • распечатать.
    • Звоните test(++a),
    • распечатать увеличенный a
  • распечатать "fin"

Ваша первая проблема в том, что вы всегда (при каждом вызове test()) распечатываете "fin". поместите это в else {...} блок, чтобы исправить это.

Ваша вторая проблема заключается в том, что вы распечатываете увеличенное значение a, поэтому вы получаете вывод. удалите второй оператор println (System.out.println(a);), чтобы исправить это.

Правильная реализация вашего метода будет выглядеть так:

public void test(int a)
{
    if(a<5) {
        System.out.print(a);
        test(++a);
    } else {
        System.out.println("fin");
    }
}
2 голосов
/ 18 февраля 2012

Попробуйте это:

public class cash
{
    public void test(int a)
    {
        if(a<5)
        {
            System.out.print(a+" ");
            test(++a);
            return;
        }
        System.out.println("fin");
    }
    public static void main(String[] argsc)
    {
        cash c=new cash();       
        c.test(1);
    }
}

Примечание: вышеуказанный код не был проверен.

EDIT

Ваш код не имел условия остановки после того, как достиг a=5; следовательно, строка System.out.print после рекурсивного вызова сама всегда выполнялась по мере извлечения стека; отсюда вывод:

1
2
3
4 -- function stops calling itself here and returns. Stack is popped
fin -- Program continues executing the line from the last recursive call (prints fin)
5 --  As above, there were 2 lines pending to execute from the previous call, the system.out.println after test(a++) 
fin  -- And the system.out.println('fin');
4  -- Stack is popped, same 2 lines as above. prints 4 since the value of a when the function was called was 4 then continues on to the next line, which prints 'fin' 
fin
... and so on
1 голос
/ 18 февраля 2012

Это то, что ваш код будет выполнять:

test(1); // Outputs "1", calls test(2), outputs "2" and "fin" after that
test(2); // Outputs "2", calls test(3), outputs "3" and "fin" after that
test(3); // Outputs "3", calls test(4), outputs "4" and "fin" after that
test(4); // Outputs "4", calls test(5), outputs "5" and "fin" after that
test(5); // Outputs "fin" after that

В основном:

"1 " + test(2) + "2" + "fin"
"1" + ("2" + test(3) + "3" + "fin") + "2" + "fin"
"1" + ("2" + ("3" + test(4) + "4" + "fin") + "3" + "fin") + "2" + "fin"
"1" + ("2" + ("3" + ("4" + test(5) + "5" + "fin") + "4" + "fin") + "3" + "fin") + "2" + "fin"
"1" + ("2" + ("3" + ("4" + ("fin") + "5" + "fin") + "4" + "fin") + "3" + "fin") + "2" + "fin"

Итак, ваш вывод правильный.

0 голосов
/ 18 февраля 2012

Проблема в вашем решении состоит в том, что условие выхода рекурсии (a больше или равно 5) выполняется всегда . Он должен выполняться только один раз , в первый раз условие выполняется, поэтому вы должны поместить его в блок else. Также плохая идея присваивать параметру (часть ++a).

Самый простой способ, которым я могу придумать для написания test метода:

public void test(int a) {
    if (a < 5) {
        System.out.print(a + " ");
        test(a + 1);
    } else {
        System.out.println("fin");
    }
}
0 голосов
/ 18 февраля 2012

Во время четвертого рекурсивного вызова вашего метода тестирования переменная увеличивается до 5, прежде чем вы вызовете метод (test (++ a)). Поскольку значение <5 ложно, оно будет продолжаться при выводе плавника и возврата (отсюда и вывод: 1 2 3 4 плавник) </p>

Однако вскоре после возврата он продолжит выполнение остальной части кода, которая выведет 5, за которым следует fin. То же самое происходит и для любой предыдущей рекурсивной итерации в вашем коде, поэтому рекурсивный вывод: X fin (где X - значение a в каждой предыдущей итерации)

0 голосов
/ 18 февраля 2012

Попробуйте код ниже ... Вы поймете, как работает эта программа

public class cash
{
    public void test(int a)
    {
    if(a<5)
    {
        System.out.print(a+" ");
        System.out.print("test 1 - " + a);
        test(++a);
        System.out.print("test 2 - " + a);
        System.out.println(a);
    }
    System.out.println("fin");
    }
    public static void main(String[] argsc)
    {
    cash c=new cash();       
    c.test(1);
    }
}

Обновление 1

Чтобы получить то, что вы хотите, используйте ниже

public class cash
{
    public void test(int a)
    {
    if(a<5)
    {
        System.out.print(a+" ");
//            System.out.print("test 1 - " + a);
        test(++a);
        if (a==5)
        System.exit(0);
//            System.out.print("test 2 - " + a);
        System.out.println(a);
    } else {
    System.out.println("fin");
    }
    }
    public static void main(String[] argsc)
    {
    cash c=new cash();       
    c.test(1);
    }
}
0 голосов
/ 18 февраля 2012

Первое, что вы делаете в рекурсии, это печатаете элемент, а затем рекурсивно вызываете функцию.

Давайте посмотрим на стек вызовов рекурсии. [мы будем обозначать каждый рекурсивный вызов его аргументом a]

Сначала вы вызываете метод только с одним элементом

| |
|1|
---

вы напечатаете «1» и вызовете рекурсивный вызов с 2, теперь верх будет:

|2|
|1|
---

Вы вводите метод снова и печатаете элемент, 2, и повторно вызываете с 3, и получаете:

|3|
|2|
|1|
---

продолжите эту логику, и вы закончите печатью 1,2,3,4 и получите трассировку стека:

|5|
|4|
|3|
|2|
|1|
---

Теперь условие не выполняется, поэтому вы печатаете только fin, а return - приводит к выталкиванию первого элемента:

|4|
|3|
|2|
|1|
---

когда вы возвращаетесь из рекурсивного вызова, вы печатаете верхнюю часть + 1 [5], а затем fin и снова извлекаете элемент из заголовка трассировки стека и получаете:

|3|
|2|
|1|
---

Теперь снова вы печатаете заголовок + 1: 4 и fin и вставляете еще один элемент ....
Продолжайте эту логику, пока стек не станет пустым, и вы получите именно то, что напечатала программа!

0 голосов
/ 18 февраля 2012

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

0 голосов
/ 18 февраля 2012

НЕТ !.O / p верен ... test(++a) будет продолжать вызывать себя снова и снова до a = 5 ... как только это будет выполнено, только после этого он напечатает следующую строку для других значений ..

test (5) -> test (4) -> test (3) -> test (2) -> test (1)

В рекурсивных функциях используется stack ... поэтому последний вход будетпервый выход ...

взгляд здесь .....

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...