Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
TP_ вторая часть_новый.doc
Скачиваний:
0
Добавлен:
01.03.2025
Размер:
183 Кб
Скачать

Рекурсия

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

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

“Правила предосторожности” при написании рекурсивных программ:

  1. Рекомендуется компилировать программу с директивой {$S+}, которая включает проверку переполнения стека (области памяти, в которой хранится состояние вызывающей подпрограммы), а так же использовать директиву {$R+} проверки диапазона переменных (тогда если будет переполнение стека, программа завершится и на экране появится сообщение об ошибке).

  2. в начале процедуры (функции), вызываемой рекурсивно, можно разместить строку if keypressed then Halt. В этом случае при зависании программы вместо перезагрузки будет достаточно нажать на любую клавишу.

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

Пример. Вычисление факториала.

n!=1*2*…*n=n*(n-1)!,

0!=1

1 способ.

Function Fact(n:integer):longint;

begin

if n=1 then Fact:=1 {n=1-барьер}

else Fact:=n*Fact(n-1)

end;

2 способ.

F:=1;

for i:=1 to n do

F:=F*i

Пример. Вывести n-е число последовательности Фибоначчи

1,1,2,3,5,8,13,…

a1,a2,a3,…

ai= 1, i=1,2

ai-1+ai-2, i>2

1 способ.(рекурсивный)

Function F(n:integer):longint;

begin

if keypressed then Halt;

if ((n=1) or (n=2)) then F:=1 {барьер}

else F:=F(n-2)+F(n-1);

end;

2 способ.

Function G(n:integer):longint;

var x,y,t: longint;

i:integer;

begin

x:=1; y:=1;

for i:=3 to n do

begin

t:=y;{t- дополнительная переменная для хранения}

y:=x+y;

x:=t;

end;

G:=y;

end;

Упражн. Вычисление целой степени вещественного числа.

y=ax, a<>0

Задача “Ханойская башня”

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

На площадке A находится пирамида из дисков, уменьшающихся от основания к вершине. Эту пирамиду в том же виде нужно перенести на площадку В, используя площадку С, как вспомогательную. При этом:

  • перекладывать можно только по одному диску;

  • класть диск можно только на диск с большим диаметром или на основание площадки.

A (исходный) В (конечный) С (промежуточный)

Пусть n – количество дисков.

  1. n=2: A→C; A→B; C→B – всего 3 хода.

  2. n=3: A→B; A→C; B→C; A→B; C→A; C→B; A→B

– всего 7 ходов.

Составим программу, по которой будет рассчитан алгоритм работы монахов для любого значения n.

Алгоритм задачи следующий:

  1. если n=0, то ничего не делать.

  2. если n>0, то 1 шаг: переместить (n-1) диск на С через В

2 шаг: переместить 1 нижний диск с А на В

3 шаг: переместить (n-1) диск с С на В через А

Program bashnja;

var n:integer;

procedure Hanoi (n:integer; A,B,C:char);

begin

if n>0 then {барьер}

begin

Hanoi (n-1, A,C,B); {1 шаг}

writeln(A, ‘=>’,B); {2 шаг}

Hanoi (n-1, C,B,A); {3 шаг}

end;

end;

begin {основная программа}

writeln (‘введите n’);

readln (n);

Hanoi (n,A,B,C);

end.

Рекурсия в графике

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

П ример. Треугольник Серпинского

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]