Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Лекции по курсу.docx
Скачиваний:
107
Добавлен:
24.02.2016
Размер:
2.8 Mб
Скачать

Лекция 15. Программирование с использованием рекурсии

15.1. Понятие рекурсии

Рекурсивным называется описание объекта, частично состоящее и оп­ределяемое с помощью самого описываемого объекта. Рекурсия - это такой способ организации вычислительного процесса, при котором подпро­грамма в ходе выполнения обращается сама к себе.

Классический пример: вычисление факториала n! = 1*2*3...(n-1)*n.

Рекурсивное описание: n! = (n-1)! * n, 0! = 1.

Рекурсивная функция:

Function fak(n:word):extended; begin

if n=0 then result:=l

else result:=fak(n-l)*n

end;

Примечание: Тип результата вычислений (extended) выбран из-за боль­шего диапазона допустимых значений быстрорастущей функции n!.

Нерекурсивная функция:

Function fak(n:word):extended; Var k:word;

begin

result:=l;

if n>l then for k:=2 to n do result:=result*k;

end;

При выполнении рекурсивной подпрограммы осуществляется много­кратный переход от текущего уровня организации алгоритма к нижнему уровню последовательно, до тех пор, пока не будет получено тривиальное решение задачи (в вышеприведенном примере, n=0). Рекурсивная форма за­писи алгоритма обычно выглядит изящнее итерационной и дает более ком­пактный текст программы, но при выполнении работает медленнее и может вызвать переполнение программного стека (исключительная ситуация ES-tackOverFlow), т. к. при каждом переходе к следующему уровню (рекурсив­ной активации подпрограммы) происходит создание и запоминание всех ее локальных и формальных параметров. В результате, после n-й активации в памяти будет находиться список из n+1 комплектов таких параметров.

Рекурсивный вызов может быть прямым„ как в вышеприведенном при­мере, и косвенным. В этом случае подпрограмма обращается к себе опосре­дованно, путем вызова другой подпрограммы, в которой содержится обраще­ние к первой.

// Опережающее описание Procedure rex(<список параметров 1>); Forward;

Procedure fox(<список параметров 2>); begin

rex(<список параметров 1>);

end;

Procedure rex; begin

fox(<список параметров 2>); end;

В этом примере обращение к процедуре rex() записано раньше, чем ее описание, что недопустимо в Pascal. Для разрешения этой ситуации ис­пользуется опережающее описание с помощью стандартной директивы For­ward.

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

15.2. Примеры рекурсивных вычислений

Найти максимальный элемент в массиве используя метод деления мас­сива пополам max (al^an) = max (max (ai...an/2), max (an/2+l^an))

type vek=array[l..50] of extended;

function maxR(x:vek; m,n:integer):extended ; var k:integer;

begin

if m=n then result:=x[m]

else begin k:=(m+n) div 2; if maxR(x,m,k)>maxR(x,k+l,n)

then result:=maxR(x,m,k)

else result:=maxR(x,k+l,n);

end; end;

Найти максимальный элемент в массиве используя очевидное соотно­шение max (al^an) = max (max(ai...an_i), an)

function maxRn(x:vek; n:integer):extended; begin

if n=l then result:=x[l]

else if maxRn(x,n-l)>x[n] then result:=maxRn(x,n-l)

else result:=x[n];

end;

ЛЕКЦИЯ 16. ПОИСК И СОРТИРОВКА МАССИВОВ