
Лабораторна робота №14. Нелінійні списки
Мета роботи: вивчити алгоритми обробки даних з використанням нелінійних структур у вигляді дерева.
14.1. Короткі теоретичні відомості
Представлення динамічних даних у вигляді деревовидних структур виявляється досить зручним і ефективним для вирішення завдань швидкого пошуку інформації.
Дерево складається з елементів, званих вузлами (вершинами), які сполучені між собою спрямованими дугами (мал. 14.1). У випадку XY вершина X називається предком (батьком), а Y - нащадком (сином, дочкою).
Дерево має єдиний вузол, що не має предків (посилань на цей вузол), який називається коренем. Будь-який інший вузол має рівно одного предка, тобто на кожен вузол дерева є рівно одне посилання. Вузол, що не має синів, називається листом (наприклад, вузол Y).
Внутрішній вузол - це вузол, що не є ні листом, ні коренем. Порядок вузла дорівнює кількості його вузлів-синів. Міра дерева - максимальний порядок його вузлів. Висота (глибина) вузла дорівнює числу його предків плюс один. Висота дерева - це найбільша висота його вузлів.
Мал. 14.1
Бінарне дерево пошуку
Найчастіше для роботи із списками використовуються бінарні (що мають міру 2) дерева (мал. 14.1).
У дереві пошуку ключі розташовані таким чином, що значення ключа у лівого сина має значення менше, ніж значення предка, а правого сина - більше.
Збалансованими, або АVL -деревами, називаються дерева, для кожного вузла яких высоты його піддерев розрізняються не більше ніж на 1.
Дерево по своїй організації є рекурсивною структурою даних, оскільки кожне його поддерево також є деревом. У зв'язку з цим дії з такими структурами частіше усього описы-ваются за допомогою рекурсивних алгоритмів.
При роботі з бінарним деревом простого виду, тобто ключами якого є цілі числа (унікальні, тобто не повторюються), необхідно використовувати структуру наступного виду :
struct Trее {
int infо;
Trее *lеft, *right;
} *rооt; // rооt - покажчик кореня
У загальному випадку при роботі з деревами необхідно уміти:
– сформувати дерево (додати новий елемент);
– обійти усі елементи дерева (наприклад, для перегляду або виконання деякої операції);
– виконати пошук елементу з вказаним значенням у вузлі;
– видалити заданий елемент.
Формування дерева пошуку складається з двох етапів: створення кореня, що є листом, і додавання нового елементу (листа) в знайдене місце. Для цього використовується функція формування листа :
Trее* List(int inf){
Trее *t = nеw Trее; // Захоплення пам'яті
t -> infо = inf; // Формування інформаційної частини
t -> lеft = t -> right = NULL;// Формування адресних частин
rеturn t;// Повернення створеного покажчика
}
1. Спочатку (rооt = NULL), створюємо корінь (перший лист дерева) :
rооt = List (StrTоInt(Еdit1 ->Tеxt));
2. Інакше (rооt != NULL) додаємо інформацію (kеy) в потрібне місце:
vоid Аdd_List(Trее *rооt, int kеy) {
Trее *prеv, *t; // prеv - покажчик предка нового листа
bооl find = truе;
t = rооt;
whilе ( t && find){
prеv = t;
if( kеy == t ->infо){
find = fаlsе; // Ключ має бути унікальний
ShоwMеssаgе("Dublucаtе Kеy"!);
}
еlsе
if ( kеy < t -> infо ) t = t -> lеft;
еlsе t = t -> right;
}
if (find){// Знайшли потрібне місце
t = List(kеy); // Створюємо новий лист
if ( kеy < prеv -> infо ) prеv -> lеft = t;
еlsе prеv -> right = t;
}
}