[Оглавление] | [<< страница] | [>>страница] |
5.3. Основные операции и возможная структура древовидной таблицы
Основными функциональными операциями над древовидными таблицами являются:
Эти операции по выполняемым функциям схожи с аналогичными операциями над бинарными деревьями поиска, однако aлгоритмы реализации их существенно различны. Это вызвано тем, каждый узел бинарного дерева поиска размещается в динамической памяти, получаемой при включении узла и освобождаемой при его удалении. Узлы же бинарного дерева в древовидной таблице размещаются в массиве (в векторной памяти). Это вызывает необходимость ведения списков занятых и свободных элементов массива. Список занятых элементов определяется указателями в узлах, начиная с корня, для ведения списка свободных элементов можно использовать один из указателей в свободных элементах. Для каждого списка необходим указатель на его начало.
Так как число элементов в массиве фиксировано, то требуется вести счетчик занятых элементов массива, а для сохранения таблицы в файле и последующего ее чтения из файла нужна информация о размере таблицы. Следовательно, таблица должна содержать некоторую управляющую информацию, включающую: указатель на корень дерева; указатель на начало списка свободных элементов; счетчик числа занятых элементов; число элементов таблицы.
Исходя из этого можно предложить такую структуру таблицы, в которой первые две строки заняты управляющей информацией. Массив имеет n элементов, первые два из которых содержат управляющую информацию, остальные m=n-2 предназначены для элементов двоичного дерева поиска.
Таблица.
Указатель на корень | Пусто | Указатель списка свободных элементов |
Счетчик занятых | Пусто | Размер таблицы m |
Левый указатель | Ключ + данные | Правый указатель/ Указатель свободного элемента |
... | ... | ... |
... | ... | ... |
Инициализация таблицы. При инициализации таблицы обнуляются все левые указатели, включая указатель на корень и счетчик занятых элементов, очищаются поля ключей и данных. В указатель списка свободных элементов заносится индекс первой свободной строки, т.е. 2. Размер таблицы m устанавливается равным либо m = n (число строк массива), либо m = n - 2 (максимальное число узлов дерева). Правые указатели, начиная с третьей строки массива (с индексом i = 2), должны показывать на последующие строки (3, 4, ..., n). Правый указатель в последней строке можно обнулять, так как возможность включения нового элемента определяется не концом списка свободных элементов, а счетчиком занятых элементов. В качестве примера рассмотрим табл., в которой поле «Ключ+данные» представлено только ключом, имеющим положительные целочисленные значения, n= 15, m = 13. Таблица 6.2
0 | 0 | 2 |
0 | 0 | 13 |
0 | 0 | 3 |
0 | 0 | 4 |
... | ... | ... |
0 | 0 | i+1 |
... | ... | ... |
0 | 0 | 14 |
0 | 0 | 15 |
Включение элемента в таблицу. Примем, что запись с дублирующим ключом в таблицу не включается.
Исходные данные для включения — таблица Т и ключ key >0.
Состояние таблицы в момент включения:
а) Узел не имеет потомков.
Если узел является корнем дерева, то:
б) Узел дерева с двумя потомками.
в) Узел дерева с одним потомком.
Если удаляемый узел является корнем дерева, то в указатель списка занятых заносим индекс следующего элемента (правого или левого) по дереву, затем выполняем пункты а) 2—5.
Если же удаляемый элемент является промежуточным узлом дерева, то в указатель предыдущего элемента заносим индекс следующего элемента, затем опять-таки выполняем пункты а) 2-
Отметим, что при удалении любого узла выполняются пункты а) 2—5.
Сохранение таблицы в файле . Исходными данными являю таблица Т и имя файла. Естественно, сохраняются только не пустые таблицы.
Восстановление таблицы из файла . Исходные данные файла. Возвращаемое значение — указатель на динамическую таблицу либо NULL в случае неудачи.
Обходы дерева в таблице . При рассмотрении деревьев в списковой памяти мы отмечали, что для управления деревом создается дескриптор, содержащий такие данные, как имя дерева, дата создания, информация об узлах дерева и обязательно указатель на корень дерева. Обращение к дереву осуществляется через дескриптор по схеме:
Указатель на дескриптор -> Дескриптор —> Корень дерева.
В простейшем случае дескриптор содержит только указатель на корень дерева, тогда обращение к дереву предельно упрощается:
Указатель на корень дерева —> Корень дерева.
Для управления деревом в древовидной таблице мы создали управляющую информацию в первых двух строках таблицы, корень дерева первоначально находится в третьей строке, а по мере удаления элементов может переместиться в любую строку таблицы, кроме первых двух. Указатель на корень дерева всегда находится в левом указателе первой строки T[0].L.
Для обхода дерева в списковой памяти мы применяли рекурсивные функции. Функция обхода содержала только один параметр: указатель на корень дерева. Применение аналогичной функции обхода в древовидной таблице потребует наличия двух параметров: указателя на таблицу (массив) и указателя на корень, содержащего индекс строки таблицы с корнем, то есть целого числа ≥2. Если таблица находится в массиве Table, то обращение к функции нисходящего обхода имеет вид: Preorder(Table, Table[0].L).
[Оглавление] | [<<страница] | [>>страница] | [В начало ] |