2. Двоичные деревья поиска
Двоичным называется дерево с максимальной
степенью вершины равной двум
В двоичном дереве каждая
вершина может иметь(или
не иметь) правого и левого
ребенка.
3. Двоичные деревья поиска
Двоичным деревом поиска называется такое
двоичное дерево в котором элементы хранятся в
соответствии с принципом упорядоченности:
Пусть вершина x-произвольная вершина двоич-
ного дерева поиска. Если вершина y находится в
левом поддереве вершины x, то выполняется
неравенство , если у – в правом
поддереве вершины x, то выполняется
неравенство
keyxkeyy →≤→
keyxkeyy →>→
4. Двоичные деревья поиска
Свойство упорядоченности позволяет просто
реализовать вывод отсортированного
множества элементов двоичного дерева поиска.
void InOrderTreeWalk(x){
if(x!=null){
InOrderTreeWalk(x->left);
Print(x);
InOrderTreeWalk(x->right);
}
}
5
3
2 5
7
8
5. Двоичные деревья поиска
Поиск элемента в двоичном дереве поиска
занимает время O(h), где h-высота дерева.
void TreeSearch(x,key){
if ((x==null)||(key=x->key)) return x;
if (key<x->key) return TreeSearch(x->left, key);
else return TreeSearch(x->right, key);
}
void IterativeTreeSearch(x,key){
while((x==null)&&(key=x->key)){
if (key<x->key) x = x->left;
else x = x->right;
} return x;}
6. Двоичные деревья поиска
void TreeMinimum(x){
while(x->left!=null)
x=x->left;
return x;
}
void TreeMaximum(x){
while(x->right!=null)
x=x->right;
return x;
}
5
3
2 5
7
8
В двоичном дереве поиска самый левый лист –
минимум, самый правый лист - максимум.
7. Двоичные деревья поиска
void TreeNext(x){
if(x->right!=null)
return TreeMinimum(x->right);
y = x->parent;
while((y!=null)&&(x==y->right)){
x = y; y = x->parent;
} return y; }
5
3
2 5
7
8
void TreePrevious(x){
if(x->left!=null)
return TreeMaximum(x->left);
y = x->parent;
while((y!=null)&&(x==y->left)){
x = y; y = x->parent;
} return y; }
8. Двоичные деревья поиска
Если вершина имеет двоичного дерева поиска
имеет двух детей, то следующая за ней
вершина не имеет левого ребенка, а
предшествующая ей вершина – правого.
Это обстоятельство используется в алгоритме
удаления вершины, для того чтобы сохранить
свойство упорядоченности для двоичного
дерева поиска.
9. Двоичные деревья поиска
5
3
2 5
7
8
void TreeInsert(root,z){
y = null; x = root;
while (x!=null){
y=x;
if (z->key < x->key) x = x->left;
else x = x->right;
}
z->parent = y;
if (y==null) root=z;
else {
if (z->key < y->key) y->left = z;
else y->right = z;
}
}
4
5
3
2 5
7
8
10. Двоичные деревья поиска
void TreeDelete(root,z){
if ((z->left==null)||(z->right==null))
y = z;
else y = TreeNext(z);
if (y->left !=null) x = y->left;
else x = y->right;
if (x!=null) x->parent = y->parent;
if (y->parent == null) root=x;
else {
if (y == y->parent->left)
y->parent->left = x;
else y->parent->right = x;
}
if (y!=z) { Copy(z,y); }
}
4
5
3
2 5
7
8
5
4
2 5
7
8
11. Двоичные деревья поиска
Операции поиска, нахождения минимального
и максимального, следующего и предыдущего
элементов, а также добавления и удаления в
двоичном дереве поиска работают со
скоростью O(h), где h – высота дерева.
Высота случайно построенного двоичного
дерева пропорциональна log n (n-общее
количество элементов). Однако это не
гарантировано и в худшем случае высота
дерева пропорциональна n.
12. Красно-черные деревья
Для того чтобы высота дерева была
пропорциональна log n, должны соблюдаться
требования, гарантирующие что глубины
любых двух листьев различаются не более чем
в два раза.
Деревья, обладающие такими свойствами,
называют сбалансированными.
Разновидностью сбалансированных деревьев
являются красно-черные деревья.
13. Красно-черные деревья
Двоичное дерево поиска называется красно-черным,
если оно обладает следующими свойствами (RB-
свойствами):
Каждая вершина – либо красная, либо черная.
Каждый лист (nil, null) – черный.
Если вершина красная – оба ее ребенка черные.
Все пути от корня к листьям содержат одинаковое
количество черных вершин.
15. Красно-черные деревья
Теорема. Красно-черное дерево с n внутренними
вершинами,(т.е. не считая null-листьев) имеет
высоту не больше 2log(n+1).
Таким образом красно-черное дерево является
сбалансированным.
16. Красно-черные деревья
Работать с красно-черными деревьями можно
так же как и с обычными двоичными деревьями
поиска. Однако при добавлении или удалении
вершины дерево может потерять RB-свойства,
т.е. разбалансироваться.
Чтобы восстановить RB-свойства, надо
перекрасить некоторые вершины и изменить
структуру дерева.
Структура дерева меняется с помощью
вращений.
17. Красно-черные деревья
x
yα
β γ
x
y
α β
γ
void LeftRotate(root,x){
y = x->right;
x->right = y->left;
if ( y->left != null) y->left->parent = x;
y->parent = x->parent;
if (x->parent == null) root = y;
else{
if (x == x->parent->left)
x->parent->left = y;
else x->parent->right= y;
}
y->left = x;
x->parent = y;
}
Левое
вращение
18. Красно-черные деревья
11
14
x
15
2
1 7
5
4
8
y
В алгоритме добавления
вершины к красно-черному
дереву вновь добавляемую
вершину окрашивают в
красный цвет, а корень всегда
оставляют черным.
После добавления вершины x (4),
не выполняется RB-свойство
№3. Вершина 5 не может иметь
красного ребенка.
19. Красно-черные деревья
Пусть y – «дядя» x. Если обе
вершины красные, то
перекрашиваем y и родителя x в
черный цвет, а «деда» x в
красный.
Теперь RB-свойство №3 не
выполняется для вершины 7.
Однако «дядя» у 7 – черный.
11
14
x 15
2
1 7
5 8
y
4
20. Красно-черные деревья
Произведем левое вращение
относительно x. Результат снова
не обладает всеми RB-
свойствами для вершины 2.
Разница по сравнению с
предыдущем случаем состоит в
том, что 2 – левый ребенок
своего родителя, а 7 – была
правым.
11
14
x
152
1
7
5
8
y
4
21. Красно-черные деревья
Перекрашиваем «деда» x в
красный цвет, родителя в
черный. Произведем правое
вращение относительно «деда»
x.
Результат обладает всеми RB-
свойствами.
11
14
15
2
1
7
5 8
4
22. Красно-черные деревья
В рассмотренном примере вершина x
(нарушающая RB-свойства дерева) всегда
была левой по отношению к своему «деду».
Если она окажется справа от «деда», то
возникают еще три случая, решающие задачу
балансировки дерева симметрично
предыдущим трем.
23. Красно-черные деревья
При удалении вершины из красно-черного
дерева действуют по тому же алгоритму что и
в обычных двоичных деревьях поиска.
Если удаляемая вершина – красная, RB-
свойства после удаления нарушены не будут.
Если удаляемая вершина – черная. Путь
проходивший через нее будет содержать на
одну черную вершину меньше (св-во №4).
24. Красно-черные деревья
D
E
A
B
C
D
E
A
B
Cα β
γ δ ε ζ γ δ
ε ζ
α β
x
x
w
w
Случай №1. Производим вращение и перекрашиваем вершины
как показано на рисунке. Случай №1 сводится таким образом к
случаям 2,3 или 4. (x- элемент вставший на место удаленной
вершины).
25. Красно-черные деревья
D
E
A
B
Cα β
γ δ ε ζ
x w
c
D
E
A
B
Cα β
γ δ ε ζ
x c
Случай №2. Перекрашиваем вершины как показано на рисунке.
Продолжаем просматривать дерево для родителя x.
26. Красно-черные деревья
D
E
A
B
Cα β
γ δ ε ζ
x w
c
D
E
A
B
C
α β
γ
δ
ε ζ
x
c
w
Случай №3. Производим вращение и перекрашиваем вершины
как показано на рисунке. Случай №3 сводится таким образом к
случаю 4.
27. Красно-черные деревья
D
E
A
B
C
D
E
A
B
Cα β
γ δ ε ζ γ δ
ε ζ
α β
x
x
w
w
c c
Случай №4. Производим вращение и перекрашиваем вершины
как показано на рисунке. Случай №4 исправляет недостаток
черных вершин и просмотр дерева можно завершить. Просмотр
также завершается если новая х будет красной.
28. Красно-черные деревья
Все словарные операции, включая добавление
и удаление вершин, работают для красно-
черных деревьев со скоростью log(n).
Красно-черные деревья – динамическая
структура данных, сочетающая в себе
динамические свойства связанных списков и
более быстрые словарные операции,
характерные для хеш-таблиц.