Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Шаповалов / lex_7-1.doc
Скачиваний:
48
Добавлен:
19.04.2015
Размер:
613.38 Кб
Скачать

7.4 Удаление вершины

Как и остальные базовые операции над красно-черными деревьями с п узлами, удаление узла выполняется за время O(lоg2n). Удаление оказывается несколько более сложной задачей, чем вставка.

RB_Delete(T,z)

1 if left[z]=nil[T] или right[z]=nil[T]

2 then yz

3 else yTree_Successor(z)

4 if left[y]nil[T]

5 then xleft[y]

6 else xright[y]

7 p[x] p[y]

8 if p[y]=nil[T]

9 then root[T] x

10 else if y=left[p[y]]

11 then left[p[y]] x

12 else right[p[y]] x

13 if y z

14 then key[z] key[y]

15 Копируем сопутствующие данныеy в z

16 if color[y]=black

17 then RB_Delete_Fixup(T,x)

18 return y

Процедура RB_DELETE представляет собой немного измененную процедуру Tree_Delete раздела 6.3. После удаления узла в ней вызывается вспомога­тельная процедура RB_Delete_Fixup, которая изменяет цвета и выполняет пово­роты для восстановления красно-черных свойств дерева.

Имеется три различия между процедурами Tree_Delete и RB_Delete. Во-первых, все ссылки на nil в Tree_Delete заменены в RB_Delete ссылками на ограничитель nil [Т]. Во-вторых, удалена проверка в строке 7 процедуры Tree_Delete (равно ли х nil), и присвоение р [х] р [у] выполняется в про­цедуре RB_Delete безусловно. Таким образом, если х является ограничителем nil [T], то его указатель на родителя указывает на родителя извлеченного из дере­ва узла у. В-третьих, в строках 16-17 процедуры RB_DELETE в случае, если узел у - черный, выполняется вызов вспомогательной процедуры RB_Delete_Fixup. Если узел у - красный, красно-черные свойства при извлечении у из дерева сохраняются в силу следующих причин:

  • никакая черная высота в дереве не изменяется;

  • никакие красные узлы не становятся соседними;

• так как у не может быть корнем в силу своего цвета, корень остается черным.

Узел х, который передается в качестве параметра во вспомогательную проце­дуру RB_DELETE_FlXUP, является одним из двух узлов: либо это узел, который был единственным потомком у перед извлечением последнего из дерева (если у у был дочерний узел, не являющийся ограничителем), либо, если у узла у нет до­черних узлов, х является ограничителем nil [T]. В последнем случае безусловное присвоение в строке 7 гарантирует, что родительским по отношению к х узлом становится узел, который ранее был родителем у, независимо от того, является ли х внутренним узлом с реальным ключом или ограничителем nil [T].Теперь мы можем посмотреть, как вспомогательная процедура RB_lNSERT_ FlXUP справляется со своей задачей восстановления красно-черных свойств дерева поиска.

Если извлекаемый из дерева в процедуре RB_Delete узел у черный, то мо­гут возникнуть три проблемы. Во-первых, если у был корнем, а теперь корнем стал красный потомок у, нарушается свойство 2. Во-вторых, если и ее, и р[у] (который теперь является также р [х]) были красными, то нарушается свойство 4, и, в-третьих, удаление у приводит к тому, что все пути, проходившие через у, теперь имеют на один черный узел меньше. Таким образом, для всех предков у оказывается нарушенным свойство 5. Мы можем исправить ситуацию, утверждая, что узел х - "сверхчерный", т.е. при рассмотрении любого пути, проходящего через х, добавлять дополнительную 1 к количеству черных узлов. При такой ин­терпретации свойство 5 остается выполняющимся. При извлечении черного узла у мы передаем его "черноту" его потомку. Проблема заключается в том, что те­перь узел х не является ни черным, ни красным, что нарушает свойство 1. Вместо этого узел х окрашен либо "дважды черным", либо "красно-черным" цветом, что дает при подсчете черных узлов на пути, содержащем х, вклад, равный, соответ­ственно, 2 или 1. Атрибут color узла х при этом остается равен либо BLACK (если узел дважды черный), либо RED (если узел красно-черный). Другими словами, цвет узла не соответствует его атрибуту color.

Процедура RB_Delete_Fixup восстанавливает свойства 1, 2 и4. Цель циклаwhile в строках 1-22 состоит в том, чтобы переместить дополнительную черноту вверх по дереву до тех пор, пока не выполнится одно из перечисленных условий.

  1. х указывает на красно-черный узел — в этом случае мы просто делаем узелх "единожды черным" в строке 23.

  2. х указывает на корень — в этом случае мы просто убираем излишнюю черноту.

  3. Можно выполнить некоторые повороты и перекраску, после которых двой­ная чернота будет устранена.

Внутри цикла while x всегда указывает на дважды черную вершину, не яв­ляющуюся корнем. В строке 2 мы определяем, является лих левым или правым дочерним узлом своего родителяр[х]. Далее приведен подробный код для си­туации, когдах - левый потомок. Для правого потомка код аналогичен и сим­метричен, и скрыт за описанием в строке 22. Указательwуказывает на второго потомка родителя х. Поскольку узелх дважды черный, узелw не может бытьnil [T] — в противном случае количество черных узлов на пути от р [х] к (едино­жды черному) листу было бы меньше, чем количество черных узлов на пути от р[х] к х.

Четыре разных возможных случая показаны на рис. 7.6. Перед тем как при­ступить к детальному рассмотрению каждого случая, убедимся, что в каждом из случаев преобразования сохраняется свойство 5. Ключевая идея заключается в необходимости убедиться, что при преобразованиях в каждом случае количество черных узлов (включая дополнительную черноту в х) на пути от корня вклю­чительно до каждого, из поддеревьев остается неизменным. Такимобразом, если свойство4выполнялось до преобразования, то оно выполняется и после него. Например, на рис.7.6а, который иллюстрирует случай 1, количе­ство черных узлов на пути от корня до поддеревьеви равно 3, как до, так и после преобразования (не забудьте о том, что узелх — дважды черный). Ана­логично, количество черных узлов на пути от корня до любого из поддеревьев 7.6бравно 2, как до, так и после преобразования. На рис.7.6б подсчет должен включать значение с, равное значению атрибутаcolor корня показанного поддерева, которое может быть либоred, либоblack. Так, на пути от корня до поддерева количество черных узлов равно 2 плюс величина, равная 1, если с равноblack, и 0, еслис равноred; эта величина одинакова до и после выполне­ния преобразований. В такой ситуации после преобразования новый узелх имеет атрибутcolor, равный с, но реально это либо красно-черный узел (если с =RED),либо дважды черный (если с =BLACK). Прочие случаи могут быть проверены аналогичным способом .

Рис. 7.6. Возможные ситуации, возникающие в циклеwhile процедурыRB_ Delete_Fixup. Темные узлы имеют цветblack, темно-серые —red, а светлые мо­гут иметь любой цвет (на рисунке показан какс иd). Греческими буквами показаны произвольные поддеревья.

Случай 1: узел w красный.

Случай 1 (строки 5-8 процедуры RB_DELETE_F[XUP и рис.7.6а) возникает, когда узелw ("брат" узлах)красный. Посколькуw должен иметь черных потомков, можно обменять цветаw ир[х], а затем выполнить левый поворот вокруг р[х] без нарушения каких-либо красно-черных свойств. Новый "брат"х, до поворота бывший одним из потомковw, теперь черный. Таким путем случайI приводится к случаю 2,3 или 4.

Случаи 2, 3 и 4 возникают при черном узле w и отличаются друг от друга цветами дочерних по отношению кw узлов.

Случай 2: узел w черный, оба его дочерних узла черные.

В этом случае (строки 10-11 процедурыRB_DELETE_FlXUP и рис.7.66) оба дочерних узлаw черные. Поскольку узелw также черный, мы можем забрать черную окраскуу х и w, сделавх единожды черным,a w — красным. Для того чтобы компенсировать удаление черной окраски ух иw, мы можем добавить дополнительный черный цвет узлу р[х], который до этого мог быть как красным, так и черным. После этого будет выполнена следующая итерация цикла, в ко­торой рольх будет играть текущий узелр[х]. Заметим, что если мы переходим к случаю 2 от случая 1, новый узелх — красно-черный, поскольку исходный узелр[х] был красным. Следовательно, значение с атрибутаcolor нового узлах равноRED и цикл завершается при проверке условия цикла. После этого новый узелхокрашивается в обычный черный цвет в строке 23.

Случай 3: узел w черный, его левый дочерний узел красный, а правый черный.

В этом случае (строки 13-16 процедуры RB_DELETE_FlXUP и рис.7.6в) узелw черный, его левый дочерний узел красный, а правый-черный. Мы можем обменять цветаw и

left [w], а затем выполнить правый поворот вокругwбез нарушения каких-либо красно-черных свойств. Новым "братом" узлах после этого будет черный узел с красным правым дочерним узлом, и таким образом мы привели случай 3 к случаю 4.

Случай 4: узел w черный, его правый дочерний узел красный.

В этом случае (строки 17-21 процедуры RB_DELETE_FlXUP и рис.7.6г) узел w черный, а его правый дочерний узел-красный. Выполняя обмен цветов и левый поворот вокругр[х], мы можем устранить излишнюю черноту вх, делая его просто черным, без нарушения каких-либо красно-черных свойств. Присвоениех указателя на корень дерева приводит к завершению работы при проверке условия цикла при следующей итерации.

Анализ.

Чему равно время работы процедуры RB_DELETE? Поскольку высота дере­ва сп узлами равнаO(log2n), общее время работы процедуры без выполне­ния вспомогательной процедурыRB_DELETE_FlXUP равноO(log2n). В процедуреRB_DELETE_FIXUP в случаях 1, 3 и 4 завершение работы происходит после выпол­нения постоянного числа изменений цвета и не более трех поворотов. Случай 2 — единственный, после которого возможно выполнение очередной итерации циклаwhile, причем указательх перемещается вверх по дереву не более чемО (log 2n) раз, и никакие повороты при этом не выполняются. Таким образом, время рабо­ты процедурыRB_Delete_Fixup составляетО (log2n), причем она выполняет не более трех поворотов. Общее время работы процедурыRB_Delete, само собой разумеется, также равноО (log2 n).

Соседние файлы в папке Шаповалов