2013-09-03 5 views
4

Я попытался найти примеры хвостовой рекурсии, и я действительно не вижу разницы между регулярным и хвостом. Если это не хвостовая рекурсия, может кто-нибудь сказать мне, почему ее нет?Является ли эта хвостовая рекурсия?

public static long fib(long index) { 

// assume index >= 0 

if (index == 0) // Base case 

    return 0; 

else 

    if (index == 1) // Base case 

    return 1; 

    else 

    // Reduction and recursive calls 

    return fib(index - 1) + fib(index - 2); 

} // end of method fib(long index) 

ответ

15

Нет, метод в вопросе не использует хвостовую рекурсию. Рекурсия хвоста легко распознается: рекурсивным шагом является последнее вещь, которая происходит в методе.

В вашем коде после оба рекурсивных вызова завершаются, есть еще одна операция - дополнение. Таким образом, метод рекурсивный, но не хвостовой рекурсивный.

Для сравнения, здесь приведена рекурсивная реализация метода fib() - обратите внимание на то, как нам нужно передать дополнительные параметры для сохранения состояния рекурсии и, что более важно, заметить, что после операции не осталось никаких операций рекурсивный вызов.

public static long fib(int n, long a, long b) { 
    return n == 0 ? b : fib(n-1, a+b, a); 
} 

Используйте это так:

fib(10, 1, 0) // calculates the fibonacci of n=10 
=> 55 

предыдущей реализации будет работать нормально до п = 92, для больших чисел вы должны будете использовать BigInteger вместо long, и лучше переключиться на итерационный алгоритм.

+0

Ваш ответ велик, за исключением этой строки: «Таким образом, метод рекурсивный, но не рекурсивный». Как вы подразумевали в начале вашего ответа, хвостовая рекурсивность является атрибутом рекурсивного вызова, а не метода. Вы можете сказать, что метод TR, если все сайты вызовов являются TR, но это упрощение, которое может смутить читателей, включая OP. – Gene

+0

@ Óscar López - Я не знаком с частью "? B:" что это делает? – BluceRee

+0

@BluceRee это условное выражение. Тот же код эквивалентен 'if (n == 0) return b; else return fib (n-1, a + b, a); ' –

4

@ Óscar López ответил на вопрос.

Причина, по которой люди заинтересованы в понимании того, является ли вызов хвостом, заключается в том, что существует оптимизация, позволяющая заменить хвостовой вызов веткой, тем самым избегая необходимости создания нового фрейма стека. Это позволяет неограниченную рекурсию хвоста в ограниченном стеке.

Однако, поскольку вы отметили вопрос с помощью java, вы должны знать, что текущие реализации Java НЕ реализуют оптимизацию хвостового вызова. Вызов с глубоким рекурсивным методом в Java может привести к ошибке StackOverflowError.

+0

. Я думаю, что IBM JDK/JRE (не помню имя) используется для оптимизировать хвостовые вызовы. – Javier

+0

Это интересно. Интересно, как им удалось обойти проблему безопасности, которая мешает им реализовать это в кодовой базе Sun/Oracle/OpenJDK ... –

Смежные вопросы