Три закона рекурсии

Подобно роботам Азимова, все рекурсивные алгоритмы должны подчиняться трём важным законам:

  1. Рекурсивный алгоритм должен иметь базовый случай.
  2. Рекурсивный алгоритм должен изменять своё состояние и двигаться по направлению к базовому случаю.
  3. Рекурсивный алгоритм должен вызывать сам себя.

Давайте рассмотрим каждый из этих законов более подробно и найдём их применение в алгоритме listsum. Первый - базовый случай - это условие, которое позволяет алгоритму остановить рекурсию. Он представляет собой задачу настолько малую, что её можно решить без применения каких-то дополнительных средств. В алгоритме listsum базовый случай - это список длиной 1.

Чтобы соблюсти второй закон, мы должны организовать изменения состояния таким образом, чтобы алгоритм двигался по направлению к базовому случаю. Изменение состояния означает модификацию каких-то данных, используемых алгоритмом. Обычно объём данных, представленных в задаче, уменьшается каким-либо образом. В алгоритме listsum наша первоначальная структура данных - это список, так что следует сфокусировать усилия по изменению состояние на списке. Поскольку базовый случай - это список единичной длины, естественным прогрессом в его сторону будет сокращение списка. Это в точности то, что происходит в строке 5 ActiveCode 2, когда мы вызываем listsum с более коротким списком.

Последний закон заключается в том, что алгоритм должен вызывать сам себя. Собственно, в этом и заключается определение рекурсии. Рекурсия - смущающая концепция для многих новичков-программистов. Как начинающий программист вы учили, что функции хороши тем, что позволяют взять большую задачу и разбить её на более мелкие части. Их можно решить, написав функцию для каждой. Когда же мы говорим о рекурсии, то может показаться, что мы собираемся зациклиться. У нас есть задача, решаемая с помощью функции, но для этого ей необходимо вызывать саму себя! Однако, логически здесь ничего не замкнуто: логика рекурсии в элегантном выражении решения задачи с помощью разбиения её на более мелкие и лёгкие подзадачи.

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

Самопроверка

Q-15: Сколько рекурсивных вызовов делается в процессе подсчёта суммы списка [2,4,6,8,10]?





Q-16: Предположим, вы собираетесь написать рекурсивную фунцию для подсчёта факториала числа. fact(n) возвращает n * (n-1) * (n-2)... Здесь факториал нуля по определению равен единице. Что будет подходящим базовым случаем?





Next Section - Фрейм стека: реализация рекурсии