Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Рекуррентные формулы. Рекурсивные алгоритмы и п...doc
Скачиваний:
11
Добавлен:
09.11.2019
Размер:
1.44 Mб
Скачать
      1. Динамическое программирование

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

Технология, называемая восходящим динамическим программированием (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

    1. Организация рекурсивных процедур и функций в 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.