
- •Основні поняття Object Pascal
- •Label { Розділ опису міток } Const { Розділ опису констант }
- •Лабораторна робота № 1 Створення простої програми у середовищі Delphi
- •Упорядкування і пошук даних
- •Лабораторна робота № 2 Упорядкування і пошук даних
- •Структуровані типи даних. Множини
- •Лабораторна робота № 3 Множини
- •Лабораторна робота № 4 Процедурні типи
- •Теоретичні відомості для виконання лабораторної роботи
- •1. Формула середніх прямокутників
- •2. Формула трапецій
- •3. Формула Сімпсона (формула парабол)
- •Pозв’язування рівнянь. Розв’язування рівнянь виду
- •Рекурсивні процедури і функції Рекурсія – це такий спосіб організації обчислювального процесу, при якому підпрограма в ході виконання звертається сама до себе.
- •Лабораторна робота № 5 Рекурсивні процедури і функції
- •Динамічні структури даних
- •Дані, які використовуються у програмі, поділяються на статичні й динамічні.
- •Вказівник може бути у трьох станах:
- •Лабораторна робота № 6 Динамічні структури даних
- •Лабораторна робота № 7 Розв’язання задачі з побудовою віконного інтерфейсу і підключенням форм Delphi
- •Лабораторна робота № 8 Розв’язання задачі з побудовою віконного інтерфейсу, підключенням форм Delphi та використанням графіки
- •Лабораторна робота № 9 Побудова проекту, що складається з декількох форм
Вказівник може бути у трьох станах:
-
визначений, містить адресу змінної, для якої виділена пам’ять;
-
невизначений (до першого присвоєння або після звільнення пам’яті);
-
помічений зарезервованим словом NIL (не вказує ні на які дані).
Значеннями вказівників є адреси змінних, розміщених у динамічній пам’яті. Для них допустима операція присвоєння, якщо вони вказують на один і той же тип даних і типізованому вказівнику можна присвоювати значення нетипізованого. Наприклад, присвоєння v1:=s1; і p1:=p2; – допустимі, а присвоєння v1:=v2 і p1:=v3; – недопустимі.
Для звернення до даних, на які вказує вказівник, за його іменем зразу ставиться значок ^. Наприклад, v1^:=5; або s1^:=v1^.
Вся динамічна пам’ять розглядається як суцільний масив байтів, який називається купою. Для виділення і звільнення динамічної пам’яті використовуються процедури:
-
Procedure New (Var P: Pointer); – резервує фрагмент купи динамічної пам’яті для розміщення змінної і поміщає в типізований вказівник P адресу першого байта.
-
Procedure Dispose (Var P: Pointer); – повертає в купу фрагмент динамічної пам’яті, який був зарезервований за типізованим вказівником P. Якщо вказівник P невизначений, то фіксується помилка.
-
Procedure GetMem (Var P: Pointer; Size: Integer); – резервує за нетипізованим вказівником P фрагмент динамічної пам’яті розміру Size (в байтах) і присвоює йому адресу цієї області.
-
Procedure FreeMem (Var P: Pointer; Size: Integer); – повертає в купу фрагмент динамічної пам’яті, який був зарезервований за нетипізованим вказівником P. Звільняти потрібно такий розмір пам’яті, який був виділений.
Розрізняють незв’язані і зв’язані динамічні дані.
Незв’язані динамічні дані аналогічні статичним, тільки вони можуть з’являтися і зникати під час виконання програми. Приклад. Моделювання масиву зі змінною верхньою межею.
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).
Рис 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).
Рис
11.3. Однозв’язний список.
Зв’язок
з попереднім елементом.
Рис 11.2. Однозв’язний список.
Зв’язок з наступним елементом.
Рис 11.5 Двозв’язний список.
Над списками виконуються операції:
-
створення;
-
включення нового елемента перед або після
-го елемента;
-
включення нового елемента перед або після елемента з заданим значенням;
-
вилучення елемента перед або після
-го елемента;
-
вилучення елемента перед або після елемента з заданим значенням;
-
вилучення елемента з заданим значенням;
-
впорядкування елементів списку;
-
виведення елементів списку;
-
та інші.
Черга – це частковий випадок однозв’язного списку, з якого елементи вилучаються спочатку і поміщаються в кінець. Черга працює за принципом першим прийшов – першим пішов. Для роботи з чергою необхідні операції:
-
додати елемент;
-
вибрати елемент;
-
очистити чергу;
-
перевірити, чи черга порожня.
Стек – це частковий випадок однозв’язного списку в який елементи додаються і вибираються з одного кінця Стек працює за принципом останнім прийшов – першим пішов. Для роботи зі стеком необхідні операції:
-
додати елемент;
-
вибрати елемент;
-
очистити стек;
-
перевірити, чи стек порожній.
Дерево
– це динамічні дані ієрархічної
структури, які відображають структурні
відношення між елементами. Елементи
дерева називаються вершинами або
вузлами, один з яких називається
коренем. Дерева можуть мати довільну
ієрархічну структуру. Оскільки від
дерева довільної структури завжди
можна перейти до бінарного дерева, то
будемо розглядати бінарні дерева. У
бінарному дереві з кожним вузлом
зв’язані два інших вузли. (Рис. 11.6).
З деревами можна виконувати такі операції:
-
створення;
-
обхід і пошук елемента;
-
пошук шляхів;
-
визначення кількості входжень елемента у дерево;
-
виведення елементів дерева;
-
та інші операції.
Рис. 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.