Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Delphi.doc
Скачиваний:
18
Добавлен:
29.10.2018
Размер:
3.35 Mб
Скачать

Вказівник може бути у трьох станах:

  • визначений, містить адресу змінної, для якої виділена пам’ять;

  • невизначений (до першого присвоєння або після звільнення пам’яті);

  • помічений зарезервованим словом 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.

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]