Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Скачиваний:
50
Добавлен:
07.02.2016
Размер:
104.45 Кб
Скачать

Var n:integer;

function fib(k,n, fk1, fk: integer): integer;

begin

if k=n then fib:= fk

else fib:= fib(k+1, n, fk, fk+fk1);

end;

begin

readln (n);

write (n, ‘-e число Фібоначі дорівнює’, fib(1,n,0,1));

end.

Обчислення починається за допомогою виклику fib(1,n, 0, 1).fk1 –k-1-е число Фібоначчі, fk- це к-е число Фібоначчі. Для к=1 fk=1. Далі зі збільшенням к збільшується і число Фібоначчі. Глибина рекурсії для такої рекурсивної функції дорівнює n.

Приклад 3.8. Відомо наступний алгоритм Евкліда знаходження найбільшого спільного дільника (НСД) невід’ємних цілих чисел, який оснований на наступних властивостях цієї величини. Нехай m та n – одночасно не дорівнюють нулю та є цілими невід’ємними числами та нехай mn. Тоді якщо n=0, то НСД(n, m)=m, а якщо n0, то для чисел m, n, та r , де r – залишок від ділення m на n, виконується таке: НСД(m, n)=НСД(n, r).

Знайдемо НДС(24, 18).З математики відомо, що ця величина дорівнює 6. Перевіримо, як працює алгоритм Евкліда.

m=24 n=18 n>0. Залишок від ділення 24 на 18 дорівнює 6. Тоді

НСД(24, 18)= НСД(18,6).

m=18 n=6 n>0 Залишок від ділення 18 на 6 дорівнює 0. Тоді

НСД(18, 6)= НСД(6,0).

n=0.Тому НСД(6,0)= 6.

Виконаємо цей алгоритм для m=15,n=13. Це взаємно прості число, тому НСД(15,13)=1.

m=15n=13n>0 Залишок від ділення 15 на 13 дорівнює 2. Тоді

НСД(15, 13)= НСД(13,2).

m=13 n=2 n>0 Залишок від ділення 13 на 2 дорівнює 1. Тоді

НСД(13, 2)= НСД(2,1).

m=2 n=1 n>0 Залишок від ділення 2 на 1 дорівнює 0. Тоді

НСД(2, 1)= НСД(1,0).

n=0.Тому НСД(1,0)= 1.

Зрозуміло, що цей алгоритм є рекурсивним. Тому складемо наступну рекурсивну функцію:

function NSD(a, b: word):word;

begin

if b=0 then NSD:= a

else NSD:=NSD(b, a mod b);

end;

Приклад 3.9. Написати програму, яка обчислює найменше к, таке, що задане натуральне n подається у вигляді суми к квадратів натуральних чисел.

Цю задачу з параметром n легко звести до самої себе з меншим значенням параметру. Для цього достатньо виділити один доданок, а число, яке залишилось, розкласти на суму квадратів. Якщо в якості першого доданку перебрати всі можливі квадрати, то тим самим будуть перебиратися всі розкладання вихідного числа в суму квадратів:

function kilsq (n:integer): integer;

Var I:integer;

min, pot: integer; {мінімальне та поточне значення числа доданків}

begin

if n<=3 then kilsq :=3

else

begin

mon:=n;

for i:=1 to trunc(sqrt(n+1)) do

begin

pot:= kilsq(n-sqr(i))+1;

if pot<min then min:= pot;

end;

kilsq:=min;

end

end;

Приклад 3.10. Цікавим є алгоритм піднесення цілого числа до натурального степеня (“індійський алгоритм”)[5]:

function pow(x, n: integer):integer;

Var t:integer;

begin

if odd(n) then t:=x else t:=1;

if n=1 then pow:=x

else pow:= t* sqr( pow(x, n div 2));

end;

Глибина рекурсії при такому алгоритмі дорівнює log2n.

Рекурсивно можна визначти також процедуру, не тільки функцію. Наведемо приклад рекурсивно визначеної процедури [8]:

procedure popeanddog1;

begin

writeln(‘У попа була собака, він її любив,’);

writeln(‘Вона вкрала кусок сала, він її убив,’);

writeln(‘Поховав і написав:’);

popeanddog1;

end;

Ця процедура при виклику буде виводити на екран відомий всім вірш багато разів. Якби розмір стеку процедур та функцій не був фіксованого розміру, то цей процес був би нескінчений. А так він зупинеться, коли відбудеться переповненя стеку.

Цей приклад підкреслює для нас важливість обовязково мати точку зупинки рекурсіїї, яку ми назвали початковим значенням. Отже, потрібно при створенні рекурсії використовувати умову, яка управляє процесом.

Можна виділити дві форми рекурсії: рекурсія, що виконується на рекурсивному спуску та рекурсія, що виконується на зворотній рекурсивній дії.

Рекурсія першого виду:

procedure Rec;

begin

S;

Соседние файлы в папке конспект лекцій 1 паск