Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Конец главы 3.doc
Скачиваний:
13
Добавлен:
05.11.2018
Размер:
926.21 Кб
Скачать

3.12. Сцепляемые очереди

В разд. 3.10 было показано, как на 2-3-дереве с п листьями выполнить каждую из операций ВСТАВИТЬ, УДАЛИТЬ, MIN и ПРИНАДЛЕЖАТЬ за время O(log n), если пользоваться значениями L и М. Сейчас покажем, как за время O(log n) выполнить каждую из операций СЦЕПИТЬ -и РАСЦЕПИТЬ. Снова будем предполагать, что элементы расположены на листьях 2-3-дерева в порядке возрастания слева направо и для каждого узла v вычисляются значения L[v] и М[v].

Операции сцепить(S1, S2) на вход подаются такие две последовательности S1 и S2, что каждый элемент из S1 меньше каждого элемента из S2; на выход она выдает конкатенацию этих последовательностей, т. е. S1S2. Если S1 и S2 представлены соответственно 2-3-деревьями T1 и T2, то мы хотим соединить T1 и T2 одно дерево T1, листьями которого являются листья дерева T1 в их первоначальном порядке и следующие за ними листья дерева Т1 в их первоначальном порядке. Это можно осуществить, вызвав процедуру ИМПЛАНТАЦИЯ(T1, T2), приведенную на рис. 3.32.

Наконец, рассмотрим операцию РАСЦЕПИТЬ. Напомним, что операция РАСЦЕПИТЬ(a, s) разбивает S на два множества S1 = {bb a и b S} и S2 = {bb>a и b S}. Для ее реализации определим процедуру ДЕЛЕНИЕ(а, T), которая расцепляет 2-3-дерево Т на два такие 2-3-дерева T1 и T2, что метки всех листьев в T1 не больше а, а метки всех листьев в T2 больше а.

Метод можно неформально описать следующим образом. Дано 2-3-дерево T, содержащее элемент а. Идем по пути из корня в лист с меткой а. Этот путь разбивает наше дерево на поддеревья, корнями которых служат не сами узлы, лежащие на нем, а их сыновья. Это иллюстрирует рис. 3.33, где слева от пути находятся деревья T1, T2 , T3 и тривиальное дерево, состоящее из одного узла v1, а справа – деревья Т4, T5 и v2.

Деревья слева от рассматриваемого пути и дерево, состоящее из одного узла а, соединяются с помощью только что описанного алгоритма конкатенации деревьев. Аналогично соединяются деревья, расположенные справа от пути. Необходимые детали даны в процедуре ДЕЛЕНИЕ (рис. 3.34).

procedure ДЕЛЕНИЕ(а, T):

begin

на пути из узла КОРЕНЬ[T] к листу с меткой а удалить все узлы, кроме этого листа;

comment В данный момент дерево Т оказалось разделенным на два леса - левый, состоящий из всех деревьев, листья которых лежат слева от а, и из узла с меткой а, и правый, состоящий из всех деревьев, листья которых лежат справа от а;

while в левом лесу более одного дерева do

begin

пусть Т' и T" два самых правых дерева в левом лесу;

ИМПЛАНТАЦИЯ(Т', Т')1

end;

while в правом лесу более одного дерева do

begin

пусть T' и T" – два самых левых дерева в правом лесу;

ИМПЛАНТАЦИЯ(T', T")

end

end

Рис. 3.34. Процедура для расцепления 2-3-дерева.

Теорема 3.7. Процедура ДЕЛЕНИЕ разбивает 2-3-дерево Т по листу а так, что все листья слева от а и сам лист а оказываются в одном 2-3-дереве, а все листья справа от а в другом. Эта процедура занимает время O(ВЫСОТА(T)). Порядок листьев сохраняется.

Доказательство. Из свойств процедуры ИМПЛАНТАЦИЯ вытекает, что деревья объединены правильно. Результат о времени работы получается из следующих соображений. Вначале число деревьев любой данной высоты не более 2, только деревьев высоты 0 может быть 3. Когда два дерева соединяются, получается дерево, высота которого не более чем на единицу больше наибольшей из высот двух исходных деревьев. В случае когда получается дерево высоты, на единицу большей высоты любого из исходных деревьев, его корень имеет степень 2. Таким образом, если соединяются три дерева высоты h, то в результате получается дерево высоты не более h + 1. Следовательно, на каждой стадии процесса число деревьев одинаковой высоты не превосходит 3.

Время, требуемое для соединения двух деревьев разной высоты, пропорционально разности их высот, а одинаковой высоты – постоянно. Поэтому объединение всех деревьев происходит за время, пропорциональное сумме числа деревьев и наибольшей из разностей высот любых двух деревьев. Таким образом, всего тратится времени порядка высоты исходного дерева. 

Заметим, что с помощью сцепляемой очереди последовательность S2 можно вставить между парой элементов последовательности S1 за время O(МАХ (log|S1|, logS2)). Если S2= b1, b2, . . . , bп, S1 = a1, a2, . . ., аm и S2 нужно вставить между элементами аi и ai+1, то можно применить операцию РАСЦЕПИТЬ(ai, S1) и разбить S1 по элементу аi на две последовательности S1= a1, .... ai; и S1' = ai+1, . . ., аm. Затем применить операцию СЦЕПИТЬ(S1, S2), результатом которой будет последовательность S3= a1, . . ., аi, b1, . . ., bn, и, наконец, операцию СЦЕПИТЬ(Sз, S1), дающую нужную последовательность.

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]