Вы находитесь на странице: 1из 28

AVL – деревья.

Группа TI-161
Двоичные деревья поиска
Двоичное дерево поиска (Binary Search Tree, BST) – это
двоичное дерево, в котором:

1) каждый узел (node) имеет не более двух дочерних узлов


(child nodes)

2) каждый узел содержит ключ (key) и значение (value)


и для него выполняются следующие условия:
 ключи всех узлов левого поддерева меньше значения
ключа родительского узла
 ключи всех узлов правого поддерева больше значения
ключа родительского узла

2
Двоичные деревья поиска (Binary Search Trees)

Key: 180
Value: Тигр

15 200
Барсук Лев

8 60 4000
Лиса Волк Слон

Min Max
35 90 600
Рысь Ягуар Медведь

9 узлов, глубина (depth) = 3


3
Двоичные деревья поиска (Binary Search Trees)

1. Операции имеют трудоемкость 1


Value
пропорциональную высоте дерева
NULL
2. В среднем случае высота дерева O(log(n)) 2
Value

3. В худшем случае элементы добавляются NULL


3
по возрастанию (убыванию) ключей – Value

дерево вырождается в список длины n


NULL
4
bstree_add(1, value) Value

bstree_add(2, value)
bstree_add(3, value)
bstree_add(4, value)
4
Двоичные деревья поиска (Binary Search Trees)

Средний случай Худший случай


Операция
(average case) (worst case)

Add(key, value) O(logn) O(n)

Lookup(key) O(logn) O(n)

Remove(key) O(logn) O(n)

Min O(logn) O(n)

Max O(logn) O(n)

5
Сбалансированные деревья поиска
 Сбалансированное дерево поиска (self-balancing
binary search tree) – дерево поиска, в котором высота
поддеревьев любого узла различаются не более чем на
заданную константу k
 Виды сбалансированных деревьев поиска:
o АВЛ-деревья (AVL tree)
o Красно-черные деревья (Red-black tree)
o B-деревья (B-tree)
o Splay tree
o AA tree
o Treap
o Scapegoat tree
o … 6
AVL-деревья
 АВЛ-дерево (AVL tree) – сбалансированное по высоте
двоичное дерево поиска, в котором у любой вершины
высота левого и правого поддеревьев различаются
не более чем на 1

 GNU libavl
 libdict
h-2
 Python avllib
h h-1
 avlmap

 Авторы:
Адельсон-Вельский Г.М., Ландис Е.М. Один алгоритм
организации информации // Доклады АН СССР. – 1962.
Т. 146, № 2. – C. 263–266. 7
AVL tree
Средний случай Худший случай
Операция
(average case) (worst case)

Add(key, value) O(logn) O(logn)

Lookup(key) O(logn) O(logn)

Remove(key) O(logn) O(logn)

Min O(logn) O(logn)

Max O(logn) O(logn)

Сложность по памяти: O(n)


8
AVL-деревья
 Основная идея
Если вставка или удаление элемента приводит
к нарушению сбалансированности дерева, то выполняется
его балансировка

 Коэффициент сбалансированности узла (balance factor)


– это разность высот его левого и правого поддеревьев
 В АВЛ-дереве коэффициент сбалансированности любого
узла принимает значения из множества {-1, 0, 1}

 Высота узла (height) – это длина наибольшего пути от


него до дочернего узла, являющего листом
 Высота листа равна 0
 Высота пустого поддерева (NULL) равна -1 9
Высота узла (Node height)

Высота пустого
поддерева (NULL) Height 3 10
равна -1

2 5 1 20

1 4 1 7 0 12

0 2 0 10
10
Коэффициент сбалансированности

Balance(x) = Balance: 1
Key:
H(Left) – H(Right) 10

0 1
5 20

1 -1 0
Высота
поддерева = 1 4 7 12

Balance(4) =
= 0 - (-1) = 1 0 0
2 10
11
Коэффициент сбалансированности

Balance(x) = Balance: 2
Key:
H(Left) – H(Right) 10

0 0
Не AVL-дерево 5 20

1 -1
Высота
поддерева = 1 4 7

Balance(4) =
= 0 - (-1) = 1 0 0
2 10
12
Балансировка дерева (Rebalancing)
 После добавления нового элемента необходимо обновить
коэффициенты сбалансированности родительских узлов
 Если любой родительский узел принял значение -2 или 2,
то необходимо выполнить балансировку поддерева путем
поворота (rotation)

 Типы поворотов:
o Одиночный правый поворот (R-rotation, single right rotation)
o Одиночный левый поворот (L-rotation, single left rotation)
o Двойной лево-правый поворот (LR-rotation, double left-right
rotation)
o Двойной право-левый поворот (RL-rotation, double right-left
rotation) 13
Правый поворот (R-rotation)
2
3  В левое поддерево добавили
элемент 1
1
 Дерево не сбалансированно
2
H(Left)=1 > H(Right)=-1
0
 Необходимо увеличить
1 высоту правого поддерева

Left Left case

14
Правый поворот (R-rotation)
2
3  Поворачиваем ребро,
связывающее корень и его
1 левый дочерний узел, вправо
2

0
1

15
Правый поворот (R-rotation)
2
3  Поворачиваем ребро,
связывающее корень и его
1 левый дочерний узел, вправо
2

0 0
1 2

0 0
1 3

Дерево
сбалансированно
16
Правый поворот (R-rotation)

P Правый поворот
в общем случае
L

T3
L
T1 T2
P
X

 В левое поддерево T1
вставлен элемент Х T2 T3
 Дерево не сбалансированно X
H(Left) > H(Right) 17
Правый поворот (R-rotation)

P Правый поворот
в общем случае
L

T3
T1 T2

X P.left = L.right
L.right = P
P.height = max(P.left.height,
P.right.height) + 1
L.height = max(L.left.height,
P.height) + 1 18
Левый поворот (L-rotation)
-2  В правое поддерево
1 вставлен элемент 3
-1
 Поворачиваем ребро,
2
0 связывающее корень и его
3 правый дочерний узел, влево

0
2

0 0
Right Right case
1 3

Дерево
сбалансированно 19
Левый поворот (L-rotation)
-2  В правое поддерево
P вставлен элемент 3
-1
 Поворачиваем ребро,
R
0 связывающее корень и его
X правый дочерний узел, влево

P.right = R.left
R.left = P
P.height = max(P.left.height, P.right.height) + 1
R.height = max(R.right.height, P.height) + 1

20
Двойной лево-правый поворот (LR-rotation)
 LR-поворот выполняется после добавления элемента
в правое поддерево левого дочернего узла дерева

P 1. L-поворот
левого поддерева P
L 2. R-поворот
нового дерева
R с вершиной P
T4
T1
T2 T3

Left Right case


X или X 21
Двойной лево-правый поворот (LR-rotation)
 LR-поворот выполняется после добавления элемента
в правое поддерево левого дочернего узла дерева

P 1. L-поворот
левого поддерева P
L

T4
T1
T2 T3 P.left = L_rotate(P.left)

X или X 22
Двойной лево-правый поворот (LR-rotation)
 LR-поворот выполняется после добавления элемента
в правое поддерево левого дочернего узла дерева

P 1. L-поворот
левого поддерева P
R

T4
T3
T1 T2
X
X 23
Двойной лево-правый поворот (LR-rotation)
 LR-поворот выполняется после добавления элемента
в правое поддерево левого дочернего узла дерева

P 2. R-поворот
нового дерева
c корнем P
R

T4
T3
T1 T2 P = R_rotate(P)
X
X 24
Двойной лево-правый поворот (LR-rotation)
 LR-поворот выполняется после добавления элемента
в правое поддерево левого дочернего узла дерева

R 2. R-поворот
нового дерева
c корнем P
L P

T1 T2 T3
T4
X X

25
Двойной лево-правый поворот (LR-rotation)
 LR-поворот выполняется после добавления элемента
в правое поддерево левого дочернего узла дерева

2 2
3 3 0
L-поворот R-поворот
2
-1 1
1 2 0 0
1 3
0 0
2 1

26
Двойной право-левый поворот (RL-rotation)
 RL-поворот выполняется после добавления элемента
в левое поддерево правого дочернего узла дерева
-2 Right Left case
-2
1
1 0
1 -1 2
R-поворот L-поворот
3 2 0 0
0 0 1 3
2 3

P.right = R_rotate(P.right)
P = L_rotate(P)
27
Повороты в АВЛ-дереве

 Любой поворот выполняется за константное время –


вычислительная сложность O(1)

 Любой поворот сохраняет свойства бинарного дерева


поиска (распределение ключей по левыми правым
поддеревьям)

28

Вам также может понравиться