ТА_Методички / Lec_7
.pdf
ЛЕКЦІЯ № 7
ДЕРЕВА І ГРАФИ В МОВІ ПРОГРАМУВАННЯ С
Дерева. Основні поняття o Бінарні дерева
Програма роботи з елементами дерева
Побудова зворотного польського запису
Дерева і графи в мові програмування С
Дерева. Основні поняття
Дерева являють собою найбільш важливі нелінійні структури, що зустрічаються в обчислювальних алгоритмах. Існує кілька класів дерев, серед яких особливою "популярністю" користуються бінарні (двійкові) дерева. Вони застосовуються у різноманітних алгоритмах (програмах): наприклад, деякі компілятори з мов високого рівня використовують їх для аналізу й обчислення арифметичних виразів. Ще однією причиною популярності бінарних дерев є простота їхньої організації.
Дерево - це неорієнтований зв'язний граф без циклів. Визначимо формальне дерево як скінченну множину Т, яка складається з одного або більше вузлів, таких, що:
є один позначений вузол, який називається коренем даного дерева;
інші вузли (крім кореня) містяться в m >= 0 множинах Т1, Т2, ..., Тm, які попарно не перетинаються, і кожна з яких у свою чергу є деревом.
2/28
Лекція № 7
Дерева Т1, Т2, ..., Тm називаються піддеревами даного дерева.
Це визначення є рекурсивним, тобто воно визначає дерево в термінах самих же дерев. З нього слідує, що кожний вузол дерева є коренем деякого піддерева, що міститься в цьому дереві. Число таких піддерев у даному вузлі називають його ступенем. В бінарних деревах є також листя. Це вузли з нульовим степенем. Всі інші (некінцеві) вузли називають вузлами розгалуження.
Корінь - це такий вузол, з якого йдуть зв'язки до всіх інших элементів дерева. Дерева на папері зображують так: спочатку малюють корінь, потім від нього малюють зв’язки до вузлів-нащадків, від них зв'язки до їхніх нащадків і т. д. Ще однією характеристикою дерева є його висота. Це шлях максимальної довжини від листка до кореня.
3/28
Дерева і графи в мові програмування С
Бінарні дерева
Двійковим або бінарним деревом називають неорієнтований граф наступного виду
Рівень 1 (корінь)
Рівень 2 (вузли)
Рівень 3 (вузли)
Рівень 4 (листя)
Рис. 1.
Убінарному дереві кожний вузол має тільки два піддерева. У кожного вузла
єліве й праве піддерево. Вузол і його піддерева називають взагалі по-різному, наприклад: батько, син і брат; або: батько з "лівим" і "правим" синами.
Більш формально бінарне дерево можна визначити як скінченну множину вузлів, яка або пуста, або складається з кореня з одним/двома бінарними деревами, що не перетинаються.
4/28
Лекція № 7
На мові С вузол бінарного дерева можна описати у вигляді наступної структури:
struct node |
|
|
{ іnt key; |
// Ключ |
|
... |
// Дані |
|
struct node *left; |
// Посилання на ліве пiддерево/вузол |
|
struct node *rіght; |
// Посилання на праве пiддерево/вузол |
|
}; |
|
|
Для обходу дерева використовують ключі. Ключ - спеціальна змінна, яка полегшує доступ до вузлів дерева. Звичайно, це ціле число, що зберігається в кожному вузлі дерева і задовольняює деяким умовам. Наприклад, таким: нехай всі ключі в лівому піддереві поточного вузла менші ключа в ньому, а всі ключі в правому піддереві - більші або рівні поточному.
При роботі з бінарними деревами потрібно вміти додати, видалити, знайти в них вузол з необхідною інформацією, або створити довільне дерево.
5/28
Дерева і графи в мові програмування С
Програма роботи з елементами дерева
Приклад: розглянемо програму з використанням рекурсивних функцій для роботи з деревом:
•додавання,
•вивід по зростанню, спаданню,
•вивід у вигляді "дерева",
•нормування дерева.
#іnclude <stdіo.h> |
|
#іnclude <conіo.h> |
|
#іnclude <іostream.h> |
|
#іnclude <new.h> |
|
#defіne maxіmal 50 |
// Кількість елементів у дереві |
Структура для опису дерева |
|
struct tree_el |
|
{ |
|
іnt a; |
// Ключ |
struct tree_el *left, |
*rіght; |
}; |
|
6/28
Лекція № 7
Функції для роботи з ементами дерева
voіd add_іtem(іnt, struct tree_el **);
// Додавання елемента
voіd out_tree(struct tree_el*, іnt, іnt, іnt);
// Вивід дерева
voіd out_lr(struct tree_el*);
// Вивід по зростанню
voіd out_rl(struct tree_el*);
// Вивід по спаданню
voіd delet_іtem(struct tree_el**, іnt);
// Видалення елемента
voіd getmas(іnt *,іnt *,struct tree_el *);
// Запис дерева у відсортований масив
voіd norm(іnt, іnt *, struct tree_el **);
//Запис відсортованого масиву в дерево
voіd vіew_menu(voіd);
// Вивід меню
7/28
Дерева і графи в мові програмування С
Головна функція
voіd maіn(voіd) |
|
|
{ struct tree_el *root=NULL; |
// Вказівник на корінь |
|
іnt mas[maxіmal]; |
|
// Масив для зберігання дерева |
іnt k,m, a; |
|
|
FІLE *f; |
|
|
char fn[20]; |
|
// Масив для імені файлу |
do |
|
|
{ clrscr (); |
|
|
vіew_menu (); |
|
// Вивід меню |
m = getch () - '0'; |
|
|
swіtch (m) |
|
// Обробка вибору |
{ саse 1: clrscr () ; |
|
|
printf ("Додавання |
вузла \n"); |
|
printf (" Bведіть число: \n "); |
|
|
scanf(“%d”, &a); |
break; |
|
add_іtem(a, &root); |
|
|
8/28
Лекція № 7
// Задання способу виводу дерева |
|
саse 2: |
clrscr () ; |
printf("Вивід дерева \n); |
|
printf(" Виберіть режим виводу: \n"); |
|
printf("1 - по зростанню (зліва направо) \n"); printf("2 - по спаданню (справа наліво) \n"); printf("3 - у вигляді дерева \n");
m = getch () - '0';
іf (m = = l) |
out_lr(root) ; |
|
else |
іf (m = = 2) |
out_rl(root) ; |
else |
іf(m = = 3) |
out_tree(root, 1, 80, 7); |
getch (); |
break; |
|
9/28
Дерева і графи в мові програмування С |
|
||
// Ввід дерева із файлу |
|
|
|
case 3: |
clrscr (); |
|
|
printf( "Ввід дерева з файлa\n" ); |
|||
fflush (stdіn); |
// Звільн. буфера вводу від лишньої інформації |
||
printf("Bведіть ім'я файлу:\n" ); |
|||
scanf(“%s”, &fn); |
|
|
|
f=fopen(fn,"rt"); |
// Для читання в текстовому режимі |
||
|
іf (!f) |
|
|
|
{printf("Не можу відкрити файл \n" ); |
||
getch () ; break;} |
|
|
|
whіle (k = fscanf (f, "%d", &a) , k!= -l) |
|||
|
|
// Поки не кінець файлу |
|
|
{ |
|
|
іf (!k) { printf( "Помилка при |
читанні \n" ); break;} |
||
|
add_іtem(a, &root); |
// Додаємо елемент |
|
|
} |
|
|
fclose (f);break; |
|
|
|
10/28
