
- •Тема: Деревья
- •Двоичные (бинарные) деревья
- •Пример: Представление троичного дерева в виде двоичного.
- •Алгоритм построения идеально сбалансированного дерева
- •Inf : Type_Inf;
- •Var NewNode:p_Tr;
- •Представление бинарных деревьев
- •Дерево двоичного поиска (ддп).
- •Основные операции с двоичными деревьями:
- •Inf : Type_Inf;
- •Ассоциативная память
- •Способы реализации ап
- •Основные операции с ап
- •3 1 2 3
- •Деревья оптимального поиска
- •Деревья цифрового поиска
3 1 2 3
1
2
Пример2.
4
2
4
1
1
3
2
3
Выполнение программы Prg_11_2.pas
Ввод
чисел 4 и 5:
ввод
RR-поворот:
Ввод чисел
числа
7:
2 и 1:
LL-поворот,
Ввод числа
3:
Ввод
числа 6:
Пример удаления элемента из дерева:
Реализация алгоритма включения элемента в сбалансированное дерево:
Procedure Search(x : integer; var Q : P_tr; var H : boolean);
Var
Q1, Q2 : P_tr;
Begin
if Q = Nil then
begin
New (Q);
H := true;
with Q^ do
begin
key := x;
count := 1;
left := Nil;
right := Nil;
bal := 0;
end;
end
else
if x < Q^.key then
begin
search (x, Q^.left, H); {выросла левая ветвь}
if H then {если высота увеличилась}
case Q^.bal of
1 : begin
Q^.bal := 0;
H := false;
end;
0 : Q^.bal := -1;
-1 : begin {балансировка}
Q1 := Q^.left;
if Q1^.bal = -1 then
begin {однократный LL-поворот}
Q^.left := Q1^.right;
Q1^.right := Q;
Q^.bal := 0;
Q := Q1;
end
else
begin {двукратный LR-поворот}
Q2 := Q1^.right;
Q1^.right := Q2^.left;
Q2^.left := Q1;
Q^.left := Q2^.right;
Q2^.right := Q;
if Q2^.bal = -1 then Q^.bal := 1
else Q^.bal := 0;
if Q2^.bal = 1 then Q1^.bal := -1
else Q1^.bal := 0;
Q := Q2;
end;
Q^.bal := Q;
H := false;
end {балансировка}
end {case}
end {if x < Q^.key}
else
if x > Q^.key
begin
search (x, Q^.right, H); {выросла правая ветвь}
if H then {если высота увеличилась}
case Q^.bal of
-1 : begin
Q^.bal := 0;
H := false;
end;
0 : Q^.bal := 1;
1 : begin {балансировка}
Q1 := Q^.right;
if Q1^.bal = 1 then
begin {однократный RR-поворот}
Q^.right := Q1^.left;
Q1^.left := Q;
Q^.bal := 0;
Q := Q1;
end
else
begin {двукратный RL-поворот}
Q2 := Q1^.left;
Q1^.left := Q2^.right;
Q2^.right := Q1;
Q^.right := Q2^.left;
Q2^.left := Q;
if Q2^.bal = 1 then Q^.bal := -1
else Q^.bal := 0;
if Q2^.bal = -1 then Q1^.bal := 1;
else Q1^.bal := 0;
Q := Q2;
end;
Q^.bal := 0;
H := false;
end {балансировка}
end {case}
end {if x > Q^.key}
else
begin
Q^.count := Q^.count + 1;
end;
End; {конец процедуры}
Из-за условия балансированности высота дерева О(log(N)),
где N- количество вершин, поэтому добавление элемента требует O(log(N)) операций.
Реализация алгоритма удаления элемента из сбалансированного дерева:
основано на алгоритме удаления из дерева, то есть, замене удаляемой вершины на самого левого потомка из правого поддерева или на самого правого потомка из левого поддерева, с учетом операции балансировки (тех же поворотов узлов).
Параметр-переменнаяю Н типа Boolean показывает уменьшение высоты поддерева, то есть, Н = True, если высота уменьшилась.
Процедуры балансировки: L_Balance и R_Balance начинают работать, когда уменьшается высота левого и правого поддеревьев соответственно.
Procedure DeleteT(x : integer; var Q : P_tr; var H : boolean);
Var
P : P_Tr; {H = false}
Procedure L_Balance(var Q : P_Tr; var H : boolean);
{H = true, левая ветвь стала короче}
Var
Q1, Q2 : P_tr;
B1, B2 : -1..1;
Begin
сase Q^.bal of
-1 : Q^.bal := 0;
0 : begin
Q^.bal := 1;
H : false;
end;
1 : begin {балансировка}
Q1 := Q^.right;
B1 := Q1^.bal;
if B1 >= 0 then
begin {однократный RR-поворот}
Q^.right := Q1^.left;
Q1^.left := Q;
if B1 = 0 then
begin
Q^.bal := 1;
Q1^.bal := -1;
H := false;
end
else
begin
Q^.bal := 0;
Q1^.bal := 0;
end;
Q := Q1;
end
else
begin {двукратный RL-поворот} Q2 := Q1^.left;
B2 := Q2^.bal;
Q1^.left := Q2^.right;
Q2^.right := Q1;
Q^.right := Q2^.left;
Q2^.left := Q;
if B2 = 1 then Q1^.bal := -1
else Q1^.bal := 0;
if B2 = -1 then Q1^.bal := 1;
else Q1^.bal := 0;
Q := Q2;
Q2^.bal := 0;
end;
end; {балансировка}
end; {case}
End; {L_balance}
Procedure R_Balance(var Q : P_Tr; var H : boolean);
{H = true, правая ветвь стала короче}
Var
Q1, Q2 : P_tr;
B1, B2 : -1..1;
Begin
сase Q^.bal of
1 : Q^.bal := 0;
0 : begin
Q^.bal := -1;
H : false;
end;
-1 : begin {балансировка}
Q1 := Q^.left;
B1 := Q1^.bal;
if B1 <= 0 then
begin {однократный LL-поворот}
Q^.left := Q1^.right;
Q1^.right := Q;
if B1 = 0 then
begin
Q^.bal := -1;
Q1^.bal := 1;
H := false;
end
else
begin
Q^.bal := 0;
Q1^.bal := 0;
end;
Q := Q1;
end
else
begin {двукратный LR-поворот} Q2 := Q1^.right;
B2 := Q2^.bal;
Q1^.right := Q2^.left;
Q2^.left := Q1;
Q^.left := Q2^.right;
Q2^.right := Q;
if B2 = -1 then Q^.bal := 1
else Q^.bal := 0;
if B2 = 1 then Q1^.bal := -1;
else Q1^.bal := 0;
Q := Q2;
Q2^.bal := 0;
end;
end; {балансировка}
end; {case}
End; {R_balance}
Procedure Del (var R : P_Tr; var H : boolean);
{H = false}
Begin
if R^.right <> Nil then
begin
Del(R^.right, H);
if H then R_Balance(R, H);
end
else
begin
P^.key := R^.key;
P^.count := R^.count;
R := R^.left;
H := true;
end;
End;
Begin
if Q = Nil then
begin
writeln (‘Дерево пусто.’);
H := falsel
end
else
if x < Q^.key then
begin
DeleteT (x, Q^.left, H);
if H then L_Balance (Q, H);
end
else
if x > Q^.key then
begin
DeleteT (x, Q^.right, H);
if H then R_Balance (Q, H);
end
else
begin {удаление Q^}
P := Q;
if P^.right = Nil then
begin
Q := P^.left;
H := true;
end
else
if P^.left = Nil then
begin
Q := P^.right;
H := true;
end
else
begin
Del (Q^.left, H);
if H then L_Balance(P, H);
end;
End; {DeleteT}
Г. М. Адельсон-Вельский и Е. М. Ландис доказали теорему, согласно которой высота АВЛ-дерева с N внутренними вершинами заключена между log2(N+1) и 1.4404*log2(N+2)-0.328, то есть высота АВЛ-дерева никогда не превысит высоту идеально сбалансированного дерева более, чем на 45 %. Для больших N имеет место оценка 1.04*log2(N). Таким образом, выполнение основных операций 1 — 3 требует порядка log2(N) сравнений. Экспериментально выяснено, что одна балансировка приходится на каждые два включения и на каждые пять исключений.