Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
algorithms.doc
Скачиваний:
29
Добавлен:
06.12.2018
Размер:
9.73 Mб
Скачать
    1. Однопроходное добавление элемента в красно-черное дерево

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

Итак, все, что нам нужно, это – не допустить реализации случая 1, т.к. случай 3 сводится к случаю 2, а последний завершает алгоритм. Это можно обеспечить, перекрашивая вершины при поиске листа, после которого следует вставить новую вершину. Иными словами, нам следует обеспечить, чтобы либо у вставляемой был бы черный родитель (тогда ничего больше делать не надо), либо у вставляемой вершины был бы черный дядя (тогда дерево можно сделать красно-черным за два поворота).

При поиске листа, после которого следует вставить новую вершину, вы, сначала рассматриваем в качестве текущей вершины p корень дерева. Далее в качестве p рассматриваем один из потомков корня, и т.д. Пусть, для определенности, от вершины p мы переходим к вершине p->left, тогда нам следует обеспечить, чтобы p->right была бы черной вершиной.

Рассмотрим все возможные случаи. Следует рассматривать только случаи, когда оба потомка p красные (легко увидеть, что случаи, когда p->left или p->right – черные нас устраивают).

1. p->par – черный, оба потомка p – красные. Тогда, все, что нужно сделать – перекрасить p и его потомков и перейти к рассмотрению следующей вершины p->left.

2. p->par – красный, причем p – правый потомок p->par, p->par – левый потомок p->par->par, оба потомка p – красные (случай, когда оба потомка – левые - аналогичен) .

Сначала, мы перекрашиваем p и его потомков. Теперь мы попали в ситуацию, аналогичную случаю 2, рассмотренному выше. Как было показано выше, за один поворот и одну перекраску проблему можно решить.

3. p->par – красный, причем p – правый потомок p->par, p->par – левый потомок p->par->par, оба потомка p – красные (случай, когда p – левый потомок p->par, p->par – правый потомок p->par->par - аналогичен).

Сначала, мы перекрашиваем p и его потомков. Теперь мы попали в ситуацию, аналогичную случаю 3, рассмотренному выше. Как было показано выше, за два поворота и одну перекраску проблему можно решить.

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

    1. Удаление элемента из красно-черного дерева

Сначала мы удаляем вершину, как в обычном дереве поиска.

Если у удаляемой вершины y всего один внутренний потомок x, то мы просто ставим x на место y. Если вершина y была красной, то проблем не возникает (черная длина дерева не изменяется). Если вершина y – черная, а x – красная, то проблем тоже нет: мы перекрашиваем вершину x, вставшую на место вершины y, в черный цвет и RB-свойства будут выполняться. Наконец, если обе вершины x и y – черные, то нам придется присвоить вершине y двойную черноту. Как с ней бороться – будет ясно далее.

Если у удаляемой вершины y два внутренних потомка w=y->right, z=y->left, то мы извлекаем следующий элемент за y (минимальный в дереве с корнем w) и ставим его на место y.

Теперь все проблемы сместились к вершине, у которой нет внутренних потомков. При ее удалении она становится фиктивной, что не будет противоречить дальнейшему алгоритму. Если данная вершины была красной, то она просто перекрашивается в черный цвет (уже – в качестве фиктивной вершины). Если же она была черной, то ей необходимо приписать двойную черноту.

Итак, задача сводится к следующей. Есть вершина в красно-черном дереве x, обладающая двойной чернотой. Все свойства красно-черного дерева выполняются. Требуется привести дерево к такому виду, что в нем все вершины будут просто черными или красными.

Мы будем производить некоторые манипуляции с окрестностью вершины x, которые будут или перебрасывать двойную черноту вверх по дереву, или окончательно приведут дерево к требуемому виду. Если корень дерева приобретет двойную черноту, мы просто сделаем его черным, что завершит работу алгоритма.

Рассмотрим различные варианты:

1)брат x – красный;

2-4: брат x – черный:

2)потомки брата x – черные;

3)правый потомок брата x – черный, левый – красный;

4)правый потомок брата x – красный.

  1. брат x красный.

x остается с двойной чернотой, но получает черного брата. Ситуация сводится к вариантам 2-4.

2) брат x – черный, потомки брата x – черные.

Одна чернота x и чернота b переходят к их родителю. Если родитель был красным, то процесс на это завершается. Иначе рассматриваем далее в качестве вершины x вершину a.

3) правый потомок брата x – черный, левый – красный.

Делаем правый поворот c-b-d и перекрашиваем вершины b и c. В результате, получаем, что правый потомок брата x – красный, т.е. приходим к случаю 4.

4) правый потомок брата x – красный, левый – не важно.

Делаем левый поворот d-b-a и делаем указанную перекраску (x становится просто черной). При этом цвет корня дерева и вершины c не должны меняться.

Разберемся с балансировкой. Пусть hb(x)=h (не забывать, что в hb(x) не учитывает сама вершина x). То hb(a)=h+2, hb(b)=h+1=hb(d)= количеству черных вершин в любой ветви, начинающейся на c. Отсюда, в результате простой проверки, получаем, что новое дерево является красно-черным.

Итак, мы завершили разбор операции удаления вершины в красно-черном дереве.

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