Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
lab 12.docx
Скачиваний:
0
Добавлен:
01.05.2025
Размер:
26.77 Кб
Скачать

2.5. Знищення динамічних об’єктів

На рис. 1 та 2 видно, що після того, як виконали оператор:

P := D

об’єкт 5 став недопустимим для програми, але в оперативній пам’яті

залишився. Це так зване “сміття”, яке забиває оперативну пам’ять. Тому такі

об’єкти необхідно знищувати. Для знищення динамічних об’єктів існує

стандартна процедура DISPOSE. Параметром цієї процедури є вказівник на

об’єкт, який необхідно знищити:

DISPOSE (P);

Після виконання цієї команди динамічний об’єкт, на який вказує

вказівник Р, перестає існувати, місце, яке він займав у пам’яті, звільняється, а

значення вказівникової змінної Р стає невизначеним. Процедура DISPOSE

знищує тільки сам об’єкт, але не вказівник на нього.

2.6. Динамічні структури даних. Рядки

Під рядком (або словом) розуміють упорядковану послідовність символів

конкретного алфавіту.

Рядок може бути поданий у вигляді масиву – тобто статичного об’єкта.

Наприклад, слово “АЛГОРИТМ” можна подати у вигляді вектора

ARRAY [1..10] OF CHAR.

119

Під час роботи з рядком найчастіше здійснюються такі три операції:

1) пошук входження заданого символу в рядок;

2) вставка заданого символу у вказане місце рядка;

3) видалення заданого символу із вказаного місця рядка.

Оскільки доступ до кожного елемента рядка, описаного як вектор,

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

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

Тобто усі елементи масиву, які розміщені після вставленої літери, необхідно

пронумерувати індексом на одиницю більшим від попереднього.

Аналогічна ситуація з видаленням визначеного елемента. Тому недоліка-

ми векторного подання рядка є:

1. На операцію вставки та видалення витрачається занадто багато часу че-

рез необхідність зсувати частину слова і пошуку маркера кінця рядка.

2. Якщо довжина рядка наперед невідома, то необхідно резервувати пам’ять

із запасом.

Але кожен рядок можна зобразити у вигляді ланцюжка символів, у якому

кожен попередній елемент містить вказівник на наступний.

Іншими словами опис рядка (ланцюжка) містить два поля: в першому –

записані символи ланцюжка (літери А, Л, Г, ...) а у другому – вказівник на

наступний елемент. Опис такого типу:

TYPE

ZV = ↑POINTER;

POINTER = RECORD

ELEM : CHAR;

NEXT : ZV

END;

Кожна ланка запису складається з двох полів: поле ELEM містить

безпосередньо символьні елементи рядка, поле NEXT містить вказівник на

наступний елемент.

При описі типу ZV ми порушили основне правило мови Паскаль: тип

POINTER використовується до того, як описується. Це єдиний випадок, коли

можна використовувати ім’я типу до його опису. Тільки у разі опису вказів-

никових типів допускається використання імені типу до його опису.

Для того, щоб сформувати рядок (рис. 6) або слово, необхідно описати

дві вказівникові змінні:

VSLOV – вказівник на слово,

VLAN – вказівник на ланку (окремий елемент).

А

NIL VSLOV *

а)

б)

А

NIL * VSLOV

VLAN

в)

А

NEXT VSLOV *

VLAN

VLAN↑.NEXT

г)

А

NEXT VSLOV *

VLAN

Л

NIL

VLAN↑.NEXT

А

NEXT VSLOV * Л

NIL

VLAN

д)

Рис. 6. Формування динамічного рядка

Вказівник VSLOV завжди буде вказувати на початок слова. При породженні:

NEW (VSLOV);

у пам’яті машини виділяється місце для розміщення динамічної

структури з двома полями:

VSLOV.ELEM

VSLOV.NEXT

' '

' '

' '

' '

' ' ' '

121

У поле ELEM – запишемо першу літеру слова, у поле NEXT – запишемо

NIL, оскільки вказівник на слово вказує лише на початок слова та з іншими

ланцюгами не зв’язаний (рис. 6, а).

Наступну, другу літеру слова необхідно розмістити у наступній ланці

ланцюга. Але якщо ми породимо знову VSLOV, то це буде вже нове слово і

зв’язку із літерою “А” не буде.

Використати вказівник VSLOV вже не можна, по-перше, цей вказівник

повинен вказувати завжди на початок слова, по-друге, літера “А” у цьому

випадку стане недоступна.

Якщо породити VLAN командою: NEW (VLAN); то втратиться зв’язок з

першою ланкою, де записана літера “А”. Тому для задання вказівника на

біжучу ланку використовується вказівник VLAN та у перший момент він буде

вказувати на першу літеру слова, тобто (рис. 6, б)

VLAN := VSLOV;

Тепер, у разі породження нового динамічного об’єкта:

NEW (VLAN↑.NEXT);

у поле NEXT елемента VLAN запишеться адреса наступного елемента,

тобто елемента, де буде записано другу літеру слова (рис. 6, в).

Записуємо у поле породженого елемента VLAN↑.NEXT значення поля

ELEM літеру “Л”, а у поле NEXT – значення NIL (оскільки невідомо, чи будуть

ще наступні ланки, див. рис. 6, г):

VLAN↑.NEXT↑.ELEM :=SYM;

VLAN↑.NEXT↑.NEXT :=NIL;

Наступний об’єкт, який повинен породжуватися VLAN↑.NEXT↑.NEXT.

Але, щоб не повторювати постійно слово NEXT, доцільно використати оператор:

VLAN := VLAN↑.NEXT;

Тобто перенести вказівник VLAN на наступну ланку (рис. 6, д).

Породження наступної ланки може виконуватися у циклі, де оператор:

VLAN := VLAN↑.NEXT;

аналогічний оператору I :=I +1 для подання рядка за допомогою вектора.

Фрагмент програми мовою Паскаль для формування слова має такий вигляд

(у разі набору з клавіатури символ вертикальної стрілки ↑ позначається ^ ):

PROGRAM DINSTR (INPUT, OUTPUT);

TYPE

ZV = ↑POINTER;__

POINTER = RECORD

ELEM : CHAR;

NEXT : ZV

END;

VAR

VLAN, VSLOV : ZV;

SYM : CHAR;

BEGIN

READ(SYM);

NEW (VSLOV);

VSLOV↑.ELEM := SYM;

VSLOV↑.NEXT := NIL;

VLAN := VSLOV;

WHILE SYM <> ’.’ DO

BEGIN

READ(SYM);

NEW(VLAN↑.NEXT);

VLAN := VLAN↑.NEXT;

VLAN↑.ELEM := SYM;

VLAN↑.NEXT := NIL;

END;

END.

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