Левосторонние красно-чёрные деревья
Определение: |
Left-leaning Red-Black Trees— . |
Содержание
[убрать]Вращения
Чтобы поддерживать красно-черные двоичное деревья поиска необходимо соблюдать следующие инвариантные свойства при вставке и удалении:
- Ни один обход от корня до листьев дерева не содержит двух последовательных красных узлов.
- Количество черных узлов на каждом таком пути одинаково.
Из этих инвариантов следует, что длина каждого пути от корня до листьев в красно-черном дереве с
Node rotateRight( h : Node) :
x = h.left
h.left= x.right
x.right= h
x.color = h.color
h.color = RED
return x
Node rotateLeft( h : Node) :
x = h.right
h.right = x.left
x.left = h
x.color = h.color
h.color = RED
return x
Переворот цветов
В красно-черных деревьях используется такая операция как
, которая инвертирует цвет узла и двух его детей. Она не изменяет количество черных узлов при любом обходе от корня до листьев дерева, но может привести к появлению двух последовательных красных узлов.
void flipColors( h : Node h) :
h.color = ! h.color
h.left.color = ! h.left.color
h.right.color =
h.right.color
Методы
void insert( key : Key, value : Value ):
root = insert(root, key, value)
root.color = BLACK
Node insert( h : Node, key : Key, value : Value):
if h == null
return new Node(key, value)
if isRed(h.left) && isRed(h.right)
colorFlip(h)
int cmp = key.compareTo(h.key)
if cmp == 0
h.val = value
else
if cmp < 0
h.left = insert(h.left, key, value)
else
h.right = insert(h.right, key, value)
if isRed(h.right) && !isRed(h.left)
h = rotateLeft(h)
if isRed(h.left) && isRed(h.left.left)
h = rotateRight(h)
return h
Value search(key : Key):
Node x = root
while x != null
int cmp = key.compareTo(x.key)
if cmp == 0
return x.val
else
if cmp < 0
x = x.left
else
if cmp > 0
x = x.right
return null
Удаление
f cient implementation of the delete operation is a challenge in many symbol-table implementa- tions, and red-black trees are no exception. Industrial-strength implementations run to over 100 lines of code, and text books generally describe the operation in terms of detailed case studies, eschewing full implementations. Guibas and Sedgewick presented a delete implementation in [7], but it is not fully speci ed and depends on a call-by-reference approach not commonly found in modern code. The most popular method in common use is based on a parent pointers (see [6]), which adds substantial overhead and does not reduce the number of cases to be handled.
The code on the next page is a full implementation of
void deleteMin()
root = deleteMin(root);
root.color = BLACK;
Node deleteMin(h : Node) if (h.left == null) return null; if !isRed(h.left) && !isRed(h.left.left) h = moveRedLeft(h); h.left = deleteMin(h.left); return fixUp(h);
Delete-the-minimum code for LLRB 2-3 trees
void deleteMin():
root = deleteMin(root)
root.color = BLACK
Node deleteMin( h : Node):
if h.left == null
return null
if !isRed(h.left) && !isRed(h.left.left)
h = moveRedLeft(h)
h.left = deleteMin(h.left)
return fixUp(h)
Node moveRedLeft(Node : h):
colorFlip(h):
if isRed(h.right.left)
h.right = rotateRight(h.right)
h = rotateLeft(h)
colorFlip(h)
return h
Node moveRedRight(h :Node ):
colorFlip(h)
if isRed(h.left.left))
h = rotateRight(h)
colorFlip(h)
return h
void delete(key : Key):
root = delete(root, key)
root.color = BLACK
Node delete(Node : h, Key : key):
if key.compareTo(h.key) < 0)
if !isRed(h.left) && !isRed(h.left.left)
h = moveRedLeft(h)
h.left = delete(h.left, key)
else
if isRed(h.left)
h = rotateRight(h)
if key.compareTo(h.key) == 0 && (h.right == null)
return null
if !isRed(h.right) && !isRed(h.right.left)
h = moveRedRight(h)
if key.compareTo(h.key) == 0
h.val = get(h.right, min(h.right).key)
h.key = min(h.right).key
h.right = deleteMin(h.right)
else
h.right = delete(h.right, key)
return fixUp(h)