
- •Область дії ідентифікаторів при використанні підпрограм
- •Класифікація способів передавання параметрів
- •Передавання параметрів засобами мови Паскаль
- •Вхідний і вихідний параметр за адресою (називають параметр-змінна).
- •Вхідний параметр за адресою (називають параметр-константа).
- •Рекурсія: основні поняття та визначення
- •Форми рекурсивних підпрограм
- •Виконання дій при рекурсивному спуску
- •Виконання дій при рекурсивному поверненні
- •Виконання дій як при рекурсивному спуску так і при рекурсивному поверненні
- •Швидке упорядкування
- •Порівняння функції і процедури
Виконання дій при рекурсивному поверненні
За наведеною в розділі "Рекурсія: основні поняття та визначення" програмою, в якій використовується рекурсивна функція, виконується обчислення факторіалу при рекурсивному поверненні. Але це не зовсім очевидно, оскільки в функції рекурсивний виклик і операція множення задіяні в одному операторі надання значень. Для більш зрозумілої демонстрації виконання дій при рекурсивному поверненні, подамо програму, з використанням функції, в якій рекурсивний виклик і операція накопичення значення факторіалу розділені явно. У функції використовується один параметр і одна локальна змінна: M – параметр-значення типу Integer: найбільший множник добутку; D – локальна змінна типу LongInt: для накопичення поточного значення факторіалу. Отже, програма, в якій використовується рекурсивна функція, що виконує обчислення при рекурсивному поверненні, може мати вигляд: |
var N : Integer; function Fact( i :Integer):LongInt; var D : LongInt; begin if i = 1 then D := 1 else D := Fact( i–1); Fact := D * i; end; begin Write('N = ',N); ReadLn(N); WriteLn(N,'! = ',Fact(N)); end. |
У таблиці покрокового виконання програми, наведеній нижче, розглянуто приклад для N = 5.
Поточний рівень рекурсії |
Рекурсивний спуск |
Рекурсивне повернення |
|
0 |
Введення N = 5; |
Fact(5) |
Виведення: 5! = 120 |
1 |
i := 5; |
D := Fact(4); |
Fact :=24 * 5 (120); |
2 |
i := 4; |
D := Fact(3); |
Fact :=6 * 4 (24); |
3 |
i := 3; |
D := Fact(2); |
Fact :=2 * 3 (6); |
4 |
i := 2; |
D := Fact(1); |
Fact := 1 * 2 (2); |
5 |
i := 1; |
D := 1; |
Fact := 1 * 1 (1); |
Виконання дій як при рекурсивному спуску так і при рекурсивному поверненні
Задача. Вивести текстовий рядок у зворотному порядку.
Розв’язування цієї задачі виконано у вигляді рекурсивної процедури Reverse. Використовується функція EoLn, яка повертає значення True при досягненні кінця рядка. |
procedure Reverse; var C : Char; begin if Not Eoln then begin Read(C); Reverse; Write(C); end; end; begin Reverse; end. |
У таблиці покрокового виконання програми, наведеній нижче, розглянуто приклад для введеного рядка 'HELLO'.
Поточний рівень рекурсії |
Рекурсивний спуск |
Рекурсивне повернення |
||
0 |
|
Reverse; |
|
|
1 |
EoLn=False; |
Введення 'H'; |
Reverse; |
Виведення 'H'; |
2 |
EoLn=False; |
Введення 'E'; |
Reverse; |
Виведення 'E'; |
3 |
EoLn=False; |
Введення 'L'; |
Reverse; |
Виведення 'L'; |
4 |
EoLn=False; |
Введення 'L'; |
Reverse; |
Виведення 'L'; |
5 |
EoLn=False; |
Введення 'O'; |
Reverse; |
Виведення 'O'; |
6 |
|
EoLn=True; |
|
|
Задача про Ханойські Вежі
Дано три стовпчики A, B, C. На стовпчику A один на одному знаходяться чотири диски різного діаметру. Причому вони розміщені так, що кожний менший диск знаходиться на більшому.
Потрібно перемістити ці чотири диски на стовпчик C, зберігши їх взаємне розміщення. Стовпчик B дозволяється використати як допоміжний. За один раз дозволяється перемістити тільки один з верхніх дисків будь-якого стовпчика. Крім того, більший диск не дозволяється класти на диск меншого діаметру.
Розв’язування.
Для визначення способу розв’язування поставленої задачі, розглянемо загальний випадок з n дисками. Якщо ми зможемо сформулювати спосіб розв’язування для n дисків в термінах способу розв’язування для n–1 диску, поставлена задача буде розв’язана, оскільки задачу для n–1 диску можна буде, в свою чергу, розв’язати в термінах n–2 дисків, і так далі до тривіального випадку з одним диском. А для випадку з одним диском (n=1) потрібно перемістити один диск із стовпчика A на стовпчик C.
Таким чином, якщо сформулювати спосіб розв’язування для n дисків в термінах n–1 диску, то одержимо алгоритм рекурсивної процедури:
if n = 1 |
|
then |
Перемістити диск із стовпчика A на стовпчик C і зупинитися. |
else |
Перемістити верхні n–1 диск із стовпчика A на стовпчик B, використовуючи стовпчик C як допоміжний. Перемістити диск, що залишився, з стовпчика A на стовпчик C. Перемістити n–1 диск із стовпчика B на стовпчик C, використовуючи стовпчик A як допоміжний. |
Програма для розв’язання поставленої задачі за допомогою рекурсивної процедури має вид:
var N : Integer;
procedure MoveDisks(Count : Integer; Source, Dest, Tmp : Char);
{Count – кількість дисків на стовпчику Source; Source – стовпчик, з якого потрібно перемістити диски; Dest – стовпчик, на який потрібно перемістити диски; Tmp – допоміжний стовпчик}
begin if n=1 then WriteLn(Source,' ', Dest) else begin MoveDisks(Count–1, Source, Tmp, Dest); WriteLn(Source,' ', Dest) MoveDisks(Count–1, Tmp, Dest, Source); end; end; begin Write('Кількість дисків – '); ReadLn(N); WriteLn('Послідовність переміщень:'); MoveDisks(N,'A','B','C') end. |