- •Оглавление
- •Глава 1. Теоретические основы применения рекурсии в программировании 5
- •Глава 2. Рекурсия в среде программирования delphi 20 введение
- •Глава 1. Теоретические основы применения рекурсии в программировании
- •Рекуррентные формулы в математике
- •Рекурсивные алгоритмы и подпрограммы
- •Примеры рекурсивных программ
- •Рекурсия и итерация
- •Сложность рекурсивных вычислений
- •Метод «разделяй и властвуй»
- •Динамическое программирование
- •Глава 2. Рекурсия в среде программирования delphi
- •Организация рекурсивных процедур и функций в Delphi
- •Примеры рекурсивных алгоритмов, процедур и функций
- •Поиск элемента в упорядоченном массиве (двоичный поиск)
- •Ханойские башни
- •Размен денег.
- •Размен денег 2
- •Вычисление суммы элементов линейного массива
- •Рекурсивное определение наибольшего общего делителя двух натуральных чисел на основе алгоритма Евклида
- •Реализация Pascal в рекурсивном виде
- •Рекурсивное нахождение чисел Фибоначчи, принадлежащих указанному диапазону значений
- •Реализация Pascal в рекурсивном виде
- •Рекурсивное определение геометрической прогрессии
- •Реализация Pascal в рекурсивном виде
- •Построение правильного многоугольника
- •Построение окружностей
- •Заключение
- •Список литературы
Динамическое программирование
Общий подход для реализации рекурсивных программ, который дает возможность получать эффективные и элегантные решения для обширного класса задач.
Технология, называемая восходящим динамическим программированием (bottom-up dynamic programming) основана на том, что значение рекурсивной функции можно определить, вычисляя все значения этой функции, начиная с наименьшего, используя на каждом шаге ранее вычисленные значения для подсчета текущего значения.
Она применима к любому рекурсивному вычислению при условии, что мы можем позволить себе хранить все ранее вычисленные значения. Что в результате позволит уменьшить временную зависимость с экспоненциальной на линейную.
Нисходящее динамическое программирование (top-down dynamic programming) – еще более простая технология. Она позволяет выполнять рекурсивные функции при том же количестве итераций, что и восходящее динамическое программирование. Технология требует введения в рекурсивную программу неких средств, обеспечивающих сохранение каждого вычисленного значения и проверку сохраненных значений во избежание их повторного вычисления.
К примеру, сохраняя вычисленные значения в статическом массиве K[1..100] (предварительно проинициализированном, к примеру, числом -1), мы явным образом исключим любые повторные вычисления.
Приведенная ниже программа вычисляет F(n) за время, пропорциональное n.
Function F( n : integer ) : longint;
Begin
if (K[n] <> -1)
then F := K[n]
else if n < 2
then F := n
else begin
t := F(n-1) + F(n-2)
K[n] := t;
F := t
end end;
Глава 2. Рекурсия в среде программирования delphi
Организация рекурсивных процедур и функций в Delphi
Подпрограммы – процедуры и функции в языке Delphi служат для выполнения специализированных операций. Delphi имеет множество стандартных подпрограмм, но всё равно приходится создавать собственные для выполнения часто повторяющихся операций с данными, которые могут меняться.
Рекурсия – важное и мощное свойство процедур и функций в Delphi. Рекурсия это возможность подпрограммы в процессе работы обращаться к самой себе. Без использования рекурсии приходилось бы применять циклы, а это усложняет чтение программы. Для понимания сути рекурсии лучше понимать рекурсивный вызов как вызов другой подпрограммы. Практика показывает, что в такой трактовке рекурсия воспринимается значительно проще и быстрее.
Приведенная ниже программа содержит функцию Factorial для вычисления факториала. Напомним, что факториал числа определяется через произведение всех натуральных чисел, меньших либо равных данному (факториал числа 0 принимается равным 1):
X! = 1 * 2 * ... * (X – 2) * (X – 1) * X.
Из определения следует, что факториал числа X равен факториалу числа (X – 1), умноженному на X. Математическая запись этого утверждения выглядит так: X! = (X – 1)! * X, где 0! = 1.
Последняя формула используется в функции Factorial для вычисления факториала:
program Console; {$APPTYPE CONSOLE} uses SysUtils; function Factorial(X: Integer): Longint; begin if X = 0 then // Условие завершения рекурсии Factorial := 1 else Factorial := Factorial(X - 1) * X; end;
begin Writeln('4! = ', Factorial(4)); // 4! = 1 * 2 * 3 * 4 = 24 Writeln('Press Enter to exit...'); Readln; end. |
При написании рекурсивных подпрограмм необходимо обращать особое внимание на условие завершения рекурсии, иначе рекурсия окажется бесконечной и приложение будет прервано из-за ошибки переполнения стека.
Рекурсия, в которой первая подпрограмма вызывает вторую, а вторая – первую называется косвенной. В этом случае первая подпрограмма будет содержать еще неизвестный идентификатор второй подпрограммы (компилятор не умеет заглядывать вперед). В результате компилятор сообщит об ошибке использования неизвестного идентификатора. Эта проблема решается с помощью предварительного описания процедур и функций.
Для реализации алгоритмов с косвенной рекурсией в языке Delphi предусмотрена специальная директива предварительного описания подпрограмм forward. Предварительное описание состоит из заголовка подпрограммы и следующего за ним зарезервированного слова forward, например:
procedure Proc; forward; function Func(X: Integer): Boolean; forward; |
После такого первичного описания в полном описании процедуры или функции можно не указывать список формальных параметров и тип возвращаемого значения (для функции). Например:
procedure Proc2(<формальные параметры>); forward; procedure Proc1; begin ... Proc2(<фактические параметры>); ... end; procedure Proc2; // Список формальных параметров опущен begin ... Proc1; ... end;
begin ... Proc1; ... end.
|