Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
AlgStr / Библиотека / РЕКУРСИЯ.doc
Скачиваний:
37
Добавлен:
23.03.2015
Размер:
89.09 Кб
Скачать
      1. Властивості рекурсивних алгоритмів

Усі рекурсивні алгоритми в цілому мають ряд властивостей, що поєднує їх з рекурсивними структурами даних і рекурсивними визначеннями, розглянутими вище.

Насамперед рекурсія може бути прямою або непрямою.

procedure A(..., x, ...); /* Пряма рекурсія */

begin

A(…, f(x), …);

end;

чи

procedure A(..., x, ...); /* Непряма рекурсія */

begin

B(…, f(x), …);

end;

procedure B(…, y, …);

begin

A(…, g(y), …);

end;

Об'єкти, породжувані рекурсивними визначеннями повинні бути кінцевими. Наслідком цієї вимоги є те, що вся сукупність рекурсивних підпрограм повинна включати таке положення, при котром у визначених окремих випадках обчислення могли б виконуватись безпосередньо без рекурсивного виклику. Тобто одна з підпрограм повинна мати приблизно такий вид:

ЯКЩО C ТО

Aпряме

ІНАКШЕ

Bрекурсивне

ВСЕ-ЯКЩО

або

ДОКИ НЕ C ПОВТОРЮВАТИ

Bрекурсивне

КІНЕЦЬ-ДОКИ

Aпряме

3) Для того, щоб виконання відповідної процедури могло завершитись, необхідно, щоб існувала деяка, зв'язана з цією програмою керуюча величина m – ціле невід’ємне число, щодо якого можна було б із упевненістю сказати, що воно СТРОГО убуває при кожному рекурсивному виклику. У найпростішому випадку роль такої керуючої величини може грати один з параметрів процедури. Така процедура може мати, наприклад, такий вид:

procedure C(n: byte; x,y,z: …);

begin

if n=0 then

Aпряме(n,x,y,z, …)

else

Bрекурсивне

end;

де всі рекурсивні виклики мають вид C(n-1, f(x), g(y), h(z), ...). Ясно, що вона після кінцевого числа рекурсивних викликів, видасть визначений результат для кожного невід’ємного аргументу n.

Але в загальному випадку ситуація не така проста. Розглянемо функцію

Чудність (n) = ЯКЩО n=1 ТО 1

ІНАКШЕ

ЯКЩО n – парне ТО Чудність(n/2)

ІНАКШЕ Чудність( (3*n+1)/2)

ВСЕ-ЯКЩО

ВСЕ-ЯКЩО

Наприклад, послідовність викликів при n=3 буде такою: 3, 5, 8, 4, 2, 1. А для n=7 такою: 7, 11, 17, 26, 13, 20, 10, 5, 8, 4, 2, 1.

      1. Як шукати рекурсивні рішення для задач (рекурсивні алгоритми)

Задача особливо зручна для рекурсивного аналізу, якщо вона може бути розкладена на сукупність підзадач такого ж типу, але меншої розмірності. У цьому випадку загальна методика аналізу містить три етапи:

Параметризація задачі. Полягає у виділенні різних елементів, від яких залежить рішення, і, зокрема розмірності розв'язуваної задачі. Причому розмірність повинна (у сприятливих випадках) убувати після кожного рекурсивного виклику.

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

Декомпозиція загального випадку. Має на меті привести його до однієї чи декількох задача в основному більш простих (меншої розмірності).

Наприклад. Ханойські вежі.

Мається три палички, на які можна надягати кільця, і n кілець різних розмірів. Спочатку всі кільця знаходяться на одній паличці (у порядку убування розмірів знизу-нагору). Їх необхідно перекласти на іншу паличку. При цьому не допускається, щоб більше кільце лежало поверх меншого і на кожнім кроці дозволяється перекладати тільки одне кільце. Задача полягає в описі послідовності перекладань кілець для заданого n – параметра задачі.

Рішення. Позначимо палички символами a, b, c. Перекладання кільця з палички X на паличку Y позначимо операцією MOVE(X, Y). Для пошуку рекурсивного рішення застосуємо описаний вище метод.

Параметризація задачі. Можна помітити, що необхідні дії будуть залежати від кількості кілець, що перекладаються, (n), від номерів паличок відкіля перекладати (X), куди перекладати (Y) і додаткової палички (Z).

Пошук тривіального випадку і його рішення. Якщо n = 0, то нічого перекладати не треба. Це і буде тривіальним випадком.

Декомпозиція загального випадку. У загальному випадку треба діяти у такий спосіб:

Спочатку перекласти n-1 кільце з палички X на додаткову паличку Z.

Потім перенести нижнє кільце з палички X на паличку Y.

І нарешті, покласти на це кільце n-1 паличку, покладені нами на додаткову паличку Z.

Згадавши загальний вид рекурсивної процедури, одержимо:

procedure Hanoi(n: byte; x,y,z: char);

begin

if n>0 then begin

Hanoi(n-1, x, z, y);

Move(x, y);

Hanoi(n-1, z, y, x)

end

end;

Неважко помітити, що в цій задачі єдина реальна дія, виконувана процедурою виконується рядком Move(x, y);. Інші служать тільки для опису послідовності рекурсивних викликів і відповідних модифікацій параметрів. Щоб зрозуміти таїнство рекурсії важливі не самі рекурсивні виклики, а те, що відбувається між цими викликами!!!

Соседние файлы в папке Библиотека