Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Лр+Структуры и алгоритмы с АТД.doc
Скачиваний:
0
Добавлен:
01.05.2025
Размер:
463.87 Кб
Скачать

Создание пустого б-дерева (продолжение)

Удаление из Б-дерева.

При удалении ключа их поддерева с корнем в узле х должно выполняться условие: узел х содержит не меньше 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. Как разреженные указатели, так и В-деревья допускают обращение к записям в отсортированной последовательности.

Все перечисленные методы намного эффективнее обычного последовательного просмотра файла. Временные различия между ними невелики и не поддаются точной аналитической оценке, особенно с учетом того, что соответствующие параметры (ожидаемая длина файла и коэффициенты заполненности блоков) трудно прогнозировать заранее.

В-деревья приобрели большую популярность как средство доступа к файлам в системах баз данных. Причина этой популярности частично заключается в их способности обрабатывать запросы, запрашивая записи с ключами, относящимися к определенному диапазону (при этом используется преимущество упорядоченности записей в основном файле в соответствии с последовательностью сортировки). Разреженный индекс обрабатывает подобные запросы так же достаточно эффективно, хотя все же менее эффективно, чем В-деревья.

В-деревья неплохо зарекомендовали себя при использовании их в качестве вторичных указателей, когда "ключи" в действительности не определяют ту или иную уникальную запись. Даже если записи с заданным значением для указанных полей вторичного индекса охватывают несколько блоков, то можно прочитать все эти записи, выполнив столько обращений к блокам, сколько существует блоков, содержащих эти записи, плюс число их предшественников в В-дереве. Если бы эти записи плюс еще одна группа такого же размера оказались бы хешированными в одном и том же сегменте, тогда поиск любой из этих групп в таблице хеширования потребовал бы такого количества обращений к блокам, которое приблизительно равняется удвоенному числу блоков, требующемуся для размещения любой из этих групп.