- •Лабораторные работы по программированию "Структуры и алгоритмы обработки данных"
- •Задание к лабораторной работе
- •Варианты задания
- •Методические указания по выполнению задания
- •Задание к лабораторной работе
- •Варианты задания
- •Методические указания по выполнению задания
- •Задание к лабораторной работе
- •Варианты задания
- •Методические указания по выполнению задания
- •Задание к лабораторной работе
- •Варианты задания
- •Методические указания по выполнению задания
- •Задание к лабораторной работе
- •Варианты задания
- •Методические указания по выполнению задания
- •Методические указания по выполнению задания (окончание)
- •Задание к лабораторной работе
- •Варианты задания
- •Методические указания по выполнению задания
- •Литература
- •Хранение данных в файлах
- •Простая организация данных
- •Ускорение операций с файлами
- •Хешированные файлы
- •Хешированные файлы (окончание)
- •Индексированные файлы
- •Индексированные файлы (окончание)
- •Несортированные файлы с плотным индексом
- •Внешние деревья поиска
- •Разветвленные деревья поиска
- •Создание пустого б-дерева
- •Создание пустого б-дерева (продолжение)
- •Создание пустого б-дерева (продолжение)
- •Создание пустого б-дерева (окончание)
- •Сравнение методов
- •Формат атд
- •Формат атд (окончание)
- •Вариант 8:
- •Атд "Хеш-таблица с цепочками коллизий"
- •Атд "Хеш-таблица с цепочками коллизий" (окончание)
- •Атд "Хеш-таблица с открытой адресацией"
- •Атд "Хеш-таблица с открытой адресацией" (окончание)
- •Атд "Итератор"
- •Описание методики тестирования хеш-функции (определение статистики c2)
- •Описание хеш-функций
- •Результаты тестирования хеш-функции
- •Описание методики тестирования трудоемкости операций
- •Описание методики тестирования трудоемкости операций (окончание)
- •Сравнительный анализ теоретических и экспериментальных оценок эффективности операций
- •Литература
Создание пустого б-дерева (продолжение)
Удаление из Б-дерева.
При удалении ключа их поддерева с корнем в узле х должно выполняться условие: узел х содержит не меньше t ключей, т.к. по правилам Б-дерева узел содержит минимум t-1 ключ. Т.е. при удалении нужно следить, чтобы в узлах на пути поиска был всегда запасной ключ.
Если в результате удаления опустел корень, то корнем становится его единственный сын и высота Б-дерева уменьшается.
При удалении возможны различные случаи:
1. Если ключ k находится в узле х, являющемся листом, то k удаляется из х (рис.1).
2. Если ключ k найден во внутреннем узле х, то:
a) если сын y узла х, предшествующий k, содержит не менее t ключей, то в его поддереве находится ключ k`, непосредственно предшествующий k. Этот ключ находится в листе поддерева с корнем y. Найти его можно за один просмотр поддерева от его корня к листу. Рекурсивно вызываем операцию для k`: удаляем k`, заменяем в х ключ k на k`(рис.2);
b) если сын z, следующий за k, содержит не менее t ключей, поступаем аналогично;
c) если и y и z содержат t-1 элементов, соединяем узел y, ключ k и узел z, помещая все в вершину y, которая теперь содержит 2t -1 ключей. Уничтожаем z и удаляем из x ключ k и указатель на z. Рекурсивно удаляем k из y (рис.3).
3. Если х - внутренний узел, но ключа k в нем нет, найдем среди сыновей узла х корень pi[x] поддерева, где должен лежать ключ k (если этот ключ вообще есть). Если pi[x] содержит не менее t ключей, можно рекурсивно удалить k из поддерева pi[x]. Если же pi[x] содержит всего t-1 элементов, то предварительно делаем шаги 3a или 3b:
a) пусть оба соседа узла pi[x] содержат t-1 элементов. Тогда объединим узел pi[x] с одним из соседей (как в случае 2c). При этом ключ, разделяющий их в узле х, станет ключом медианой нового узла (рис.4).
b) пусть pi[x] содержит t-1 элементов, но один из его соседей содержит по крайней мере t элементов (соседом называем такого сына узла х, который отделен от pi[x] ровно одним ключом разделителем). Тогда добавим сыну pi[x] элемент из узла х, разделяющий pi[x] и его правого соседа, а в узел х вместо него поместим самый левый ключ этого соседа. При этом самый левый сын соседа превращается в самого правого сына узла pi[x]. Аналогично поступаем для левого соседа (рис.5).
Создание пустого б-дерева (окончание)
Описанный алгоритм требует возврата к уже просмотренному узлу (случаи 2a, 2b). Это происходит, когда требуется удалить элемент из внутренней вершины. К счастью большинство узлов Б-дерева - листья и эти случаи редки.
Операция требует 0(h) обращений к диску. Вычисления требуют 0(th)=0(t logtn) времени. Иллюстрация:
Рис.1. Удаление 6 (случай 1).
Рис.2. Удаление 13 (случай 2а).
Рис.3. Удаление 7 (случай 2c).
Рис.4. Удаление 4 (случай 3a).
Рис.5. Рис.5. Удаление 2 (случай 3b).
Сравнение методов
В качестве возможных методов внешних файлов были рассмотрены хеширование, разреженные индексы и В-деревья. Интересно было бы сравнить количество обращений к блокам, связанное с выполнением той или иной операции с файлами, у разных методов.
Хеширование зачастую является самым быстрым из трех перечисленных методов; оно требует в среднем двух обращений к блокам по каждой операции (не считая обращений к блокам, которые требуются для просмотра самой таблицы сегментов), если количество сегментов достаточно велико для того, чтобы типичный сегмент использовал только один блок. Но в случае хеширования затруднительно обращаться к записям в отсортированной последовательности.
Разреженный индекс для файла, состоящего из n записей, позволяет выполнить операции с файлами, ограничиваясь использованием примерно 2+log(n/b*b1) обращений к блокам в случае двоичного поиска, где b - количество записей, помещающихся в один блок, а b1 - количество пар ключ-указатель, умещающихся в один блок для индексного файла. В-деревья позволяют выполнить операции с файлами с использованием примерно 2+logm/2(n/b) обращений к блокам, где m-максимальное количество сыновей у внутренних узлов, что приблизительно равняется b1. Как разреженные указатели, так и В-деревья допускают обращение к записям в отсортированной последовательности.
Все перечисленные методы намного эффективнее обычного последовательного просмотра файла. Временные различия между ними невелики и не поддаются точной аналитической оценке, особенно с учетом того, что соответствующие параметры (ожидаемая длина файла и коэффициенты заполненности блоков) трудно прогнозировать заранее.
В-деревья приобрели большую популярность как средство доступа к файлам в системах баз данных. Причина этой популярности частично заключается в их способности обрабатывать запросы, запрашивая записи с ключами, относящимися к определенному диапазону (при этом используется преимущество упорядоченности записей в основном файле в соответствии с последовательностью сортировки). Разреженный индекс обрабатывает подобные запросы так же достаточно эффективно, хотя все же менее эффективно, чем В-деревья.
В-деревья неплохо зарекомендовали себя при использовании их в качестве вторичных указателей, когда "ключи" в действительности не определяют ту или иную уникальную запись. Даже если записи с заданным значением для указанных полей вторичного индекса охватывают несколько блоков, то можно прочитать все эти записи, выполнив столько обращений к блокам, сколько существует блоков, содержащих эти записи, плюс число их предшественников в В-дереве. Если бы эти записи плюс еще одна группа такого же размера оказались бы хешированными в одном и том же сегменте, тогда поиск любой из этих групп в таблице хеширования потребовал бы такого количества обращений к блокам, которое приблизительно равняется удвоенному числу блоков, требующемуся для размещения любой из этих групп.
