8.3. Более сложные случаи рекурсии
Пусть функция
с натуральными аргументами и значениями
определена рекурсивно условиями
где

- некоторое число, а

и

-
известные функции.
Другими словами,
значение функции 
в точке

выражается через
значение 
в точке

. При этом
предполагается, что для любого

в последовательности
рано или поздно встретится

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

в точках этой последовательности, идя справа
налево.
Еще более сложный случай из следующей задачи вряд ли
встретится на практике (а если и встретится, то проще
рекурсию не устранять, а оставить). Но тем не менее: пусть
функция
с натуральными аргументами и значениями
определяется соотношениями
где

- некоторое число, а

,

и

- известные
функции. Предполагается, что если взять
произвольное число
и начать применять к нему функции

и

в произвольном
порядке, то рано или поздно получится

.
8.3.2.
Написать нерекурсивную программу вычисления
.
Решение. Можно было бы сначала построить дерево,
у которого в корне находится
, а в сыновьях
вершины
стоят
и
- если только
не
равно нулю.
Затем вычислять значения функции, идя от листьев к корню.
Однако есть и другой способ.
Обратной польской записью (или постфиксной записью )
выражения называют запись, где знак функции стоит после
всех ее аргументов, а скобки не используются. Вот несколько
примеров:
Постфиксная запись выражения позволяет удобно вычислять его
с помощью

.
Этот калькулятор имеет
стек, который мы будем представлять
себе расположенным горизонтально (числа вынимаются
и кладутся справа), и клавиши - числовые и функциональные.
При нажатии на клавишу с числом это число кладется в
стек.
При нажатии на функциональную клавишу соответствующая
функция применяется к нескольким аргументам у вершины
стека. Например, если в
стеке были числа
и нажата функциональная клавиша

, соответствующая
функции от двух аргументов, то в
стеке окажутся числа
Перейдем теперь к нашей задаче. В процессе вычисления
значения функции
мы будем работать со стеком чисел,
а также с последовательностью чисел и символов f, l, r, h, которую мы будем интерпретировать как
последовательность нажатий клавиш на стековом калькуляторе.
Инвариант такой:
Пусть нам требуется вычислить
значение 
. Тогда
вначале мы помещаем в
стек число

, а последовательность
содержит единственный символ
f. (При этом
инвариант
соблюдается.) Далее с последовательностью и
стеком
выполняются такие преобразования:
Здесь

,

,

- числа,

-
последовательность
чисел,

- последовательность чисел и символов
f,
l,
r,
h. В последней строке предполагается, что

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