- •СТРУКТУРЫ ДАННЫХ И АЛГОРИТМЫ
- •Глава 1 Линейные списки
- •Понятие структуры данных
- •Тип указатель
- •Линейный список
- •Линейный однонаправленный (односвязный) список
- •Линейный двунаправленный (двусвязный) список
- •Практическое задание «Линейные списки»
- •Задачи для самостоятельной работы
- •Контрольные вопросы
- •Глава 2 Структуры данных стек и очередь
- •Понятие структуры данных стек и очередь
- •Структура данных стек
- •Структура данных очередь
- •Пример решения задачи с использованием стека
- •Практическое задание «Стеки и очереди»
- •Задачи для самостоятельной работы
- •Контрольные вопросы
- •Глава 3 Древовидные структуры данных
- •Понятие структуры данных дерево
- •Представление структуры бинарное дерево в памяти
- •Обход дерева
- •Основные операции над деревом
- •Ввод дерева
- •Практическое задание «Бинарные деревья»
- •Задачи для самостоятельной работы
- •Контрольные вопросы
- •Глава 4 Структура данных таблица
- •Понятие структуры данных таблица
- •Представление таблицы в памяти
- •Организация хеш-таблиц
- •Выбор функции расстановки
- •Разрешение коллизии
- •Операции над таблицами
- •Практическое задание «Управление таблицами»
- •Задачи для самостоятельной работы
- •Контрольные вопросы
- •Глава 5 Алгоритмы упорядочения данных
- •Понятие операции упорядочения
- •Алгоритмы упорядочения
- •Сортировка слиянием
- •Основные алгоритмы сортировки посредством сравнений
- •Улучшенные алгоритмы сортировки сравнением
- •Практическое задание «Алгоритмы сортировки»
- •Задачи для самостоятельной работы
- •Контрольные вопросы
- •Библиографический список
if (t->left != NULL) PUSH(q, t->left); if (t->right != NULL) PUSH(q, t->right);
} while (!EMPTY(Q));
}
}
Основные операции над деревом
а) поиск элемента в дереве. Операция заключается в прохождении узлов дерева в одном из рассмотренных выше порядке. При прохождении дерева поиска достаточно пройти только то поддерево, которое возможно содержит искомый элемент;
б) включение элемента в дерево. Операция заключается в добавлении листа (исключая сбалансированное дерево – включение элемента в сбалансированное дерево приводит, как правило, к его перестройке) в какое-то поддерево. При включении нового элемента в дерево поиска лист добавляется в то поддерево, в котором не нарушается отношение порядка;
в) удаление элемента из дерева. Операция заключается в изменении связей между дочерними и родительскими, по отношению к удаляемому, элементами (исключая сбалансированное дерево – удаление элемента из сбалансированного дерева приводит, как правило, к его перестройке). При удалении необходимо рассматривать три случая (удаляемый элемент на рис. 3.4 помечен символом x): удаление листа (см. рис. 3.4, а), удаление элемента с одним потомком (см. рис. 3.4, б), удаление элемента с двумя потомками (см. рис. 3.4, в).
При удалении элемента степени 2 из дерева поиска изменять связи необходимо так, чтобы не нарушалось установленное в дереве отношение порядка. Лучшим вариантом в этом случае будет перемещение на место удаляемого элемента либо самого правого листа из левого поддерева удаляемого элемента, либо самого левого листа из правого поддерева удаляемого элемента;
76
г) сравнение деревьев (проверка деревьев на равенство). Операция заключается в прохождении обоих деревьев в одном порядке. Операция заканчивается, когда будут пройдены оба дерева, либо одно из них, либо
X
X 
X
А |
б |
в |
|
Рис. 3.4 |
|
соответствующие элементы окажутся не равными, либо в одном из деревьев будет обнаружено отсутствие соответствующего элемента. Только в случае равенства деревьев оба дерева будут пройдены одновременно;
д) копирование дерева. Операция заключается в прохождении исходного дерева и построении нового дерева с такой же структурой как исходное дерево и с элементами, информационные поля которых равны информационным полям соответствующих элементов исходного дерева.
Примеры операций над деревом:
– поиск элемента по значению, результат поиска – наличие / отсутствие элемента в дереве. Поиск осуществляется при прямом обходе дерева:
77
struct tree
{
char elem;
tree *left, *right;
}
struct list
{
tree *el; list *next;
}
typedef list dstack;
stack *push(tree *t, stack *s); int pop(tree **t, stack **s);
int findtree(tree *t, char x)
{
int f = 0;
stack *s = NULL;
while (t != NULL && !f)
{
if (t->elem == x) f = 1;
else
{
if ( t->left != NULL && t->right != NULL)
{
S = push(t->right, s); t = t->left;
}
else
if (t->left = = NULL && t->right = =NULL)
{
if (!pop(&t, &s))
78
t = NULL;
}
else
t = t->left != NULL ? t->left : t->right;
}
}
return f;
}
– поиск и подсчет числа элементов на заданном уровне n (рекурсивная реализация, прямой обход):
int find2(tree *t, int n)
{
if (t != NULL)
{
if (n != 0)
return find2(t->left, n - 1) + find2(t->right, n - 1);
return1;
}
return 0;
}
– включение элемента в дерево поиска:
tree *InsertTree(tree *t, char x)
{
tree *r = new tree, *p; r->elem = x;
r->left = r->right = NULL; if (!t)
return r;
79
