- •10. Рекурсивні процедури і функції Рекурсія – це такий спосіб організації обчислювального процесу, при якому підпрограма в ході виконання звертається сама до себе.
- •Лабораторна робота № 10 Рекурсивні процедури і функції
- •Розрізняють незв’язані і зв’язані динамічні дані.
- •Лабораторна робота № 11 Динамічні структури даних
- •12. Файли
- •Лабораторна робота № 12 Текстові файли
Розрізняють незв’язані і зв’язані динамічні дані.
Незв’язані динамічні дані аналогічні статичним, тільки вони можуть з’являтися і зникати під час виконання програми.
Приклад. Моделювання масиву зі змінною верхньою межею.
Program LABR11_1;
{$APPTYPE CONSOLE}
uses Sysutils;
TYPE Tvector = array[1..1] of integer;
VAR vt: ^ Tvector; {Типізований вказівник}
pn: Pointer; { Нетипізований вказівник}
n, i, j: integer;
BEGIN
{Введення початкових даних}
writeln(‘Введіть розмір масиву n<=200’);
readln(n);
{Розрахунок розміру пам’яті для розміщення }
{n елементів масиву}
j:=n*sizeof(integer);
{Виділення динамічної пам’яті}
GetMem (pn, j);
vt:=pn;
writeln(‘Введіть елементи масиву ’);
for i:=1 to n do
read(vt^[i]);
{Виведення масиву по п’ять елементів у рядку}
for i:=1 to n do
if i mod 5 <> 0 then write(vt^[i]:6)
else writeln(vt^[i]:6);
{Звільнення динамічної пам’яті}
FreeMem(pn, j);
readln;
END.
З
Дані
Вказівники
Рис 11.1. Елемент зв’язаної структури динамічних даних.
Дані можуть бути як простими, так і структурованими. Наприклад,
TYPE Tdan1 = integer;
Tdan2 = record
p: string[20];
rn: word;
pos: string[15];
end;
dan1 = record
x1: Tdan1;
v1:Tvk1;
end;
dan2 = record
x2: Tdan2;
v2:Tvk2;
end;
Tvk1 = ^dan1;
Tvk2 = ^dan2;
VAR p1: Tvk1;
P2: Tvk2;
BEGIN
. . . . . . . . . . . .
p1^.x1:=5;
p2^.x2.p:=’Шевченко’;
. . . . . . . . . . .
END.
У наведеному прикладі у випадку типу Tdan1 елементами динамічних даних будуть цілі числа, а у випадку Tdan2 – записи. Звернення до елементів динамічних даних здійснюється за допомогою складених імен.
До зв’язаних динамічних структур даних належать: списки, черги, стеки, дерева.
Список – це динамічна структура лінійно зв’язаних елементів даних. При роботі зі списками використовуються вказівники на початок (L) і кінець (K) списку. Списки бувають: однозв’язні, зі зв’язком з наступним (Рис 11.2) або попереднім (Рис 11.3) елементом; однозв’язні циклічні, зі зв’язком останнього елемента з першим (Рис 11.4); двозв’язні, зі зв’язками з наступним і попереднім елементами одночасно (Рис 11.5).
NIL .
. .
Рис 11.2. Однозв’язний список.
Зв’язок з наступним елементом.
NIL
.
. .
Рис 11.3. Однозв’язний список.
Зв’язок з попереднім елементом.
L
.
. .
Рис 11.4 Однозв’язний циклічний список.
NIL
NIL
.
. .
Рис 11.5 Двозв’язний список.
Над списками виконуються операції:
створення;
включення нового елемента перед або після -го елемента;
включення нового елемента перед або після елемента з заданим значенням;
вилучення елемента перед або після -го елемента;
вилучення елемента перед або після елемента з заданим значенням;
вилучення елемента з заданим значенням;
впорядкування елементів списку;
виведення елементів списку;
та інші.
Черга – це частковий випадок однозв’язного списку, з якого елементи вилучаються спочатку і поміщаються в кінець. Черга працює за принципом першим прийшов – першим пішов. Для роботи з чергою необхідні операції:
додати елемент;
вибрати елемент;
очистити чергу;
перевірити, чи черга порожня.
Стек – це частковий випадок однозв’язного списку в який елементи додаються і вибираються з одного кінця Стек працює за принципом останнім прийшов – першим пішов. Для роботи зі стеком необхідні операції:
додати елемент;
вибрати елемент;
очистити стек;
перевірити, чи стек порожній.
Дерево – це динамічні дані ієрархічної структури, які відображають структурні відношення між елементами. Елементи дерева називаються вершинами або вузлами, один з яких називається коренем. Дерева можуть мати довільну ієрархічну структуру. Оскільки від дерева довільної структури завжди можна перейти до бінарного дерева, то будемо розглядати бінарні дерева. У бінарному дереві з кожним вузлом зв’язані два інших вузли. (Рис. 11.6).
З деревами можна виконувати такі операції:
створення;
обхід і пошук елемента;
пошук шляхів;
визначення кількості входжень елемента у дерево;
виведення елементів дерева;
та інші операції.
a
c nil
e nil nil
f nil
d nil nil
b
h nil
nil
Рис. 11.6. Бінарне дерево.
Приклад. Розробити програму, яка створює список, елементи якого – цілі числа. За один прохід цього списку знаходить і виводить: всі елементи менші ніж a за порядком їх розміщення; всі елементи із проміжку [a, b] в оберненому порядку до їх розміщення; всі елементи більші ніж b за порядком їх розміщення.
При проходженні списку зразу будемо виводити всі елементи менші ніж зa порядком їх розміщення, елементи із проміжку [a, b] будемо поміщати у стек, а елементи більші ніж b у чергу. По завершенні проходу виведемо стек і чергу. Програма у консольному режимі роботи має вигляд:
program LABR11_2;
{$APPTYPE CONSOLE}
uses SysUtils;
{ Опис списку }
TYPE Tel = integer;
Tvsp = ^sp;
sp = record
dsp: Tel;
vsp: Tvsp;
end;
{ Опис стеку }
Tvst = ^st;
st = record
dst: Tel;
vst: Tvst;
end;
{ Опис черги }
Tvch = ^ch;
ch = record
dch: Tel;
vch: Tvch;
end;
{ Створення списку }
Procedure StvSp(Var l: Tvsp);
Var p, q: Tvsp;
c: Tel;
h: char;
Begin
repeat
readln(c);
new(q);
q^.dsp:=c;
q^.vsp:=NIL;
if l = NIL then l:=q
else p^.vsp:=q;
p:=q;
write('Продовжити введення (y/n) ->');
readln(h);
until (h='n') or (h='N');
End;
{ Помістити елемент у стек }
Procedure PushSt(Var s: Tvst; el: Tel);
Var q: Tvst;
Begin
new(q);
q^.dst:=el;
q^.vst:=s;
s:=q;
End;
{ Вибрати елемент із стеку }
Procedure PopSt(Var s: Tvst; Var el: Tel);
Var q: Tvst;
Begin
q:=s;
el:= q^.dst;
s:=q^.vst;
dispose(q);
End;
{ Перевірка чи стек порожній }
Function PustoSt(Var s: Tvst):boolean;
Begin
if s=NIl then result:=false
else result:=true;
End;
{ Помістити елемент у чергу }
Procedure PushCh(Var qp, qk: Tvch; el: Tel);
Var q: Tvch;
Begin
new(q);
q^.dch:=el;
q^.vch:=NIL;
if qp=NIL then qp:=q
else qk^.vch:=q;
qk:=q;
End;
{ Вибрати елемент із черги }
Procedure PopCh(Var qp, qk: Tvch; Var el: Tel);
Var q: Tvch;
Begin
q:=qp;
el:= q^.dch;
qp:=q^.vch;
dispose(q);
End;
{ Перевірка чи черга порожня }
Function PustoCh(Var qp, qk: Tvch): boolean;
Begin
if qp=NIl then result:=false
else result:=true;
End;
{ Основна програма}
VAR l, w: Tvsp;
s: Tvst;
qp, qk: Tvch;
a, b, c:Tel;
BEGIN
l:=NIL; s:=NIL; qp:=NIL; qk:=NIL;
{Введення початкових даних}
writeln ('Введіть a < b');
readln(a, b);
writeln ('Введіть список');
StvSp(l);
writeln ('Числа < a: ');
w:=l;
while w<>NIL do
Begin
{Виведення чисел < a }
if w^.dsp<a then write(w^.dsp:6);
{Запис чисел із проміжку [a, b] у стек }
if (a <= w^.dsp) and (w^.dsp <= b) then
PushSt(s, w^.dsp);
{Запис чисел >b у чергу }
if w^.dsp > b then PushCh(qp, qk, w^.dsp);
w:=w^.vsp;
End;
writeln;
{ Виведення чисел із проміжку [a, b] }
writeln (' Чисел із проміжку [a, b]');
while PustoSt(s) do
Begin
PopSt(s, c);
write(c:6);
End;
writeln;
{Виведення чисел >b }
writeln ('Числа > b');
while PustoCh(qp, qk) do
Begin
PopCh(qp, qk, c);
write(c:6);
End;
readln;
END.