Сложная рекурсия
Косвенная рекурсия возникает в том случае, когда некоторая функция обращается к другой функции, а та в свою очередь вызывает первоначальную функцию.
Если обычную рекурсию можно уподобить уроборосу (рис. 3), то образ сложной рекурсии можно почерпнуть из известного детского стихотворения, где «Волки с перепуга, скушали друг друга». Представьте себе двух съевших друг друга волков, и вы поймете сложную рекурсию.
Рис. 3. Уроборос – змей, пожирающий свой хвост. Рисунок из алхимического трактата «Synosius» Теодора Пелеканоса (1478г).
Рис. 4. Сложная рекурсия.
Итак, возможна чуть более сложная схема: функция A вызывает функцию B, а та в свою очередь вызывает A. Это называется сложной рекурсией.
При этом оказывается, что описываемая первой процедура должна вызывать еще не описанную. Чтобы это было возможно, требуется использовать опережающее описание.
Для предотвращения зацикливания одна или обе функции должны проверять условие завершения. При косвенной рекурсии возникают ссылки вперед. Один из рекурсивных модулей, вызывающих друг друга, описывается предварительно добавлением к заголовку функции ключевого слова FORWARD. Предварительное указание называется директивой.
По правилам синтаксиса языка Паскаль каждая вызываемая подпрограмма должна быть описана до ее вызова. Но если подпрограмма А вызывает подпрограмму В, а В вызывает А, то получается замкнутый круг. Для подобных ситуаций принято следующее правило: одна из рекурсивных, вызывающих друг друга подпрограмм, описывается предварительно следующим образом:
Пример: Опережающее описание процедуры B позволяет вызывать ее из процедуры A.
Здесь forward - директива компилятору, указывающая, что текст процедуры В помещен ниже
procedure B(n: integer); forward; {Опережающее описание второй процедуры}
procedure A(n: integer); {Полное описание процедуры A}
begin
writeln(n);
B(n-1);
end;
procedure B(n: integer); {Полное описание процедуры B}
begin
writeln(n);
if n<10 then
A(n+2);
end;
Результат работы:
Если в основной программе вызвать А(1), или А(2) или …. А(9), то будут выведены числа
вида 9 8 10 9 11 10 (для А(9))
вида 7 6 8 7 9 8 10 9 11 10 (для А(7)) и т.п.
Если в основной программе вызвать А(10), то будут выведены числа 10 9 11 10
Если в основной программе вызвать А(11), то будут выведены числа 11 10
Если в основной программе вызвать А(56), то будут выведены числа 56 55
Если в основной программе вызвать А(888), то будут выведены числа 888 887