3.6 AVL

Transcription

3.6 AVL
3.6 AVL-Bäume
(AVL = Adel’son-Velskii und Landis (1962))
2-3-Bäume. . .
– sind Basis der B-Bäume,
– sind gut auf weitere Operationen erweiterbar
(SPLIT, CONCATENATE),
– haben Worstcase-Zeiten von O(log n), aber
– sie nutzen den Speicherplatz nicht gut.
AVL-Bäume. . .
– haben Worstcase-Zeiten von O(log n),
– nutzen Speicherplatz besser, aber
– sind nicht so gut auf weitere Operationen erweiterbar.
. – Seite 326/726
Da Tiefe eines Baumes mit einem Knoten 0 ist, sei Tiefe eines
leeren Baumes −1.
AVL-Baum ist
– ein binärer Suchbaum
(→ bessere Platzausnutzung als 2-3-Baum),
– bei dem jeder Knoten einen Balancegrad
bal(v) ∈ {−1, 0, +1} hat.
bal(v)
v
T1
:= d(T1 ) − d(T2 ).
T2
. – Seite 327/726
Beispiel 1:
15
7
3
30
9
22
10
19
43
57
Beispiel 2:
20
10
15
5
1
32
8
43
16
ACHTUNG:
Einschränkung für Balancegrad bedeutet nicht, dass alle Blätter
auf zwei Ebenen liegen.
. – Seite 328/726
Was bringt die AVL-Baum-Eigenschaft?
Die Tiefe eines AVL-Baumes mit n Daten beträgt
mindestens ⌈log(n + 1)⌉ − 1 und
1
höchstens log(√5+1)−1
· log n + 1 ≈ 1, 44 log n + 1.
Also nur ca. 44 % schlechter als bei
vollständig balancierten Bäumen.
Die untere Schranke gilt für alle binären Bäume, da sie bei Tiefe d
höchstens 1 + 2 + 22 + · · · + 2d = 2d+1 − 1 Daten enthalten können.
. – Seite 329/726
Beweis der oberen Schranke:
Wie schon z. B. bei 2-3-Bäumen vorher gehen wir indirekt vor
und berechnen zunächst
A(d) := minimale Anzahl von Knoten in AVL-Bäumen
der Tiefe d.
Offensichtlich: A(0) = 1:
A(1) = 2:
oder
d ≥ 2: 1 Wurzel v , 1 Teilbaum T ′ der Tiefe d − 1,
1 Teilbaum T ′′ der Tiefe d′ ≤ d − 1
Da |bal(v)| ≤ 1, ist d′ ≥ d − 2.
Wenn wir die Knotenzahl minimieren wollen:
T ′ hat A(d − 1) Knoten,
T ′′ hat A(d − 2) Knoten.
. – Seite 330/726
Also Rekursionsgleichung:
A(0) = 1, A(1) = 2,
A(d) = 1 + A(d − 1) + A(d − 2) für d ≥ 2.
Rekursionsgleichung für Fibonacci-Zahlen Fib(d), d ∈ N:
Fib(0) = 1, Fib(1) = 1,
Fib(d) = Fib(d − 1) + Fib(d − 2) für d ≥ 2.
Leonardo da Pisa (figlio di Bonaccio)
(ca. 1180 – ca. 1241)
. – Seite 331/726
Fibonaccis Kaninchen:
t = 0:
Fib(0)
=1
t = 1:
Fib(1)
=1
t = 2:
Fib(2)
=2
t = 3:
Fib(3)
=3
t = 4:
Fib(4)
=5
t = 5:
Fib(5)
=8
Geschlossene Formel für Fibonacci-Zahlen:
1 k+1 b k+1 Fib(k) = √ Φ
+Φ
,
5
wobei
√
1+ 5
≈ 1, 68 (Zahl des „goldenen Schnittes“);
Φ :=
2
√
1− 5
b
Φ :=
≈ −0, 68.
2
Damit:
1 k+1
Fib(k) ≥ √ Φ
−1 .
5
Minimale Knotenanzahl A(d) versus Fibonacci-Zahlen Fib(d):
0
d:
A(d):
1
Fib(d): 1
1 2 3 4
5
6
7
2 4 7 12 20 33 54
1 2 3 5
8 13 21
Behauptung: A(d) = Fib(d + 2) − 1.
Beweis: Vollständige Induktion.
Induktionsanfang siehe oben.
Behauptung sei gezeigt für alle d′ ≤ d − 1.
A(d)
Ind.-Vor.
1 + A(d − 1) + A(d − 2)
Ind.-Vor.
1 + Fib(d + 1) − 1 + Fib(d) − 1
Ind.-Vor.
Fib(d + 2) − 1.
=
=
=
(Behauptung)
. – Seite 332/726
Wenn ein AVL-Baum n Daten enthält und Tiefe d hat, gilt
A(d) ≤ n,
also:
Fib(d + 2) − 1 ≤ n.
Mit Hilfe der geschlossenen Formel für Fibonacci-Zahlen:
1 d+3
√ Φ
− 1 ≤ Fib(d + 2) ≤ n + 1.
5
Hatten (letzte Folie):
1 d+3
√ Φ
− 1 ≤ n + 1.
5
Auflösen nach d:
√
d+3
Φ
≤ 5(n + 1) + 1
√
d + 3 ≤ logΦ ( 5(n + 1) + 1)
√
d ≤ logΦ ( 5(n + 1) + 1) − 3
{z
}
|
≤ 6n
1
≤ logΦ (6n) − 3 = logΦ n + logΦ (6) − 3 ≤
log n + 1.
| {z } |
{z
}
log Φ
=
Wegen log Φ = log
√
5+1
2
log n
log Φ
≤1
√
= log( 5 + 1) − 1 fertig.
. – Seite 333/726
SEARCH(x):
Wie in binären Suchbäumen Zeit O(log n).
– Zwischen log n und 1, 44 log n Vergleiche.
– Bei 2-3-Bäumen zwischen log3 n ≈ 0, 63 log n und log n Knoten,
aber pro Knoten ein oder 2 Vergleiche.
. – Seite 334/726
INSERT(x) nach erfolgloser Suche und
Abspeicherung des Suchpfades:
Wie in binären Suchbäumen, aber:
Einschränkung für Balancegrad danach evtl. verletzt.
Beobachtungen:
– Genau für die Knoten auf dem
Suchpfad kann sich der Balancegrad geändert haben.
(Genau die Knoten, die Teilbaum
haben, in den x eingefügt wurde.)
x v
nil
– Es ist bal(v) = 0 für den
neuen Knoten v .
nil
. – Seite 335/726
Rebalancierung nach INSERT(x):
– Wir durchlaufen den Suchpfad rückwärts.
– Abbruchkriterium: Teilbaum, in den x eingefügt wurde, hat
seine Tiefe nicht verändert.
– Ansonsten (wird sich zeigen) ist seine Tiefe um 1 gewachsen.
Dann weiter mit Fallunterscheidung.
„Induktionsanfang“: Am Elter des neuen Knotens, der x enthält,
wächst Tiefe offensichtlich um höchstens 1.
Der auf dem Suchpfad erreichte Knoten heiße v .
O. B. d. A. ist die Tiefe des rechten Teilbaumes um 1 gewachsen.
. – Seite 336/726
1. Fall: bal(v) = 1 (der alte Wert).
+1
0
v
d−1
d
v
d
alt
d
Also bal(v) := 0.
Tiefe von T (v) unverändert
Rebalancierung
abgeschlossen.
neu
2. Fall: bal(v) = 0.
0
−1
v
d
d
alt
v
d+1
d
Also bal(v) := −1.
Tiefe von T (v) um 1 gewachsen.
Rebalancierung am Elter
fortsetzen.
neu
. – Seite 337/726
3. Fall: bal(v) = −1.
1. Unterfall:
alt
−1
Suchpfad von v aus war rechts-rechts-. . .
Das Problem kommt von außen.
v
neu
−2
v
w
0
v 0
w
w
Linksrotation
A
d
d+1
d+2
B
Calt
A
B
C
A
B
C
Also: bal(w) := 0,
bal(v) := 0.
Die Tiefe von T (w) ist gleich der alten Tiefe von T (v).
Rebalancierung abgeschlossen.
. – Seite 338/726
2. Unterfall: Suchpfad von v aus war rechts-links-. . .
Das Problem kommt von innen.
−1
alt
w
d−2
d−1
d
v 0
neu
z
0
A
−2
v +1
z
−1
w
Calt
D
v−2
w
0
z
Rechts an (w, z),
dann links an
(v, w).
A
B
−2
Rechts-LinksRotation
A
B
D
B
C
C
D
Also: bal(w) := 0,
bal(v) := 1,
bal(z) := 0.
Die Tiefe von T (w) ist gleich der alten Tiefe von T (v).
Rebalancierung abgeschlossen.
. – Seite 339/726
2. Unterfall: Suchpfad von v aus war rechts-links-. . .
Das Problem kommt von innen.
−1
alt
w
d−2
d−1
d
v 0
neu
z
0
A
−2
v +1
z
−1
w
Calt
D
0
+1
D
B
w0
v
Rechts an (w, z),
dann links an
(v, w).
A
B
Rechts-LinksRotation
z
B
A
C
D
C
Also: bal(w) := 0,
bal(v) := 1,
bal(z) := 0.
Die Tiefe von T (w) ist gleich der alten Tiefe von T (v).
Rebalancierung abgeschlossen.
. – Seite 339/726
2. Unterfall: Suchpfad von v aus war rechts-links-. . .
Das Problem kommt von innen.
−1
alt
w
d−2
d−1
d
v 0
neu
z
0
A
−2
v +1
z
−1
w
Calt
D
0
0
v
Rechts an (w, z),
dann links an
(v, w).
A
B
Rechts-LinksRotation
C
D
w−1
z
C
A
B
D
B
Variante: d(B) = d(C) + 1
Dann: bal(w) := 0,
bal(v) := 0,
bal(z) := −1.
Die Tiefe von T (w) ist gleich der alten Tiefe von T (v).
Rebalancierung abgeschlossen.
. – Seite 339/726
Noch ein Sonderfall: w ist der eingefügte Knoten.
bal(w) := 0,
v
w
bal(v) := 0,
z
nil
v
z
bal(z) := 0.
w nil
nil nil nil
nil
Rebalancierung
abgeschlossen.
nil
nil
Erkenntnisse für INSERT:
– Stets nur ein Teilbaum in der Tiefe gewachsen und
zwar um +1.
– Nach einer Rotation oder Doppelrotation ist die
Rebalancierung abgeschlossen.
– Um diese Stelle zu finden, muss evtl. der ganze Suchpfad
zurückgelaufen werden.
– Zeit O(1) pro Knoten auch auf dem Suchpfad →
Zeit O(log n) insgesamt.
. – Seite 341/726
INSERT(4)
4
0
INSERT(5)
4
INSERT(7)
−1
5
4
L
−2
5
−1
7
5
4
2
1
5
4
0
INSERT(2)
0
0
0
7
0
INSERT(1)
1
7
5 alter Wert 1
0
4
0
2
1
2
7
R
0
1
0
. – Seite 342/726
1 (wieder richtig)
5
2
1
0
0
7 0
4
LR
INSERT(3)
5
2
0
1
2
−1
0
5
7 0
L
4
4
1
2
1
3
2
INSERT(6)
0
4
0
5
2
3
0
RL
alter Wert 0
4
−1
R
7
0
5
−2
4
R
L
2
1
0
3
0
7
0
1
0
3
0
7
6
4
2
1
0
6
0
1
3
5
6
0
0 (wieder richtig)
0
3
1
7
5
0
0
7
0
. – Seite 343/726
DELETE(x) nach erfolgreicher Suche und Abspeicherung
des Suchpfades:
– Genau wie in binären Suchbäumen (also evtl. das größte
Datum y < x suchen, y und x austauschen, x entfernen).
– Wenn Knoten u gelöscht wird, kann Tiefe des Elters v von u
um 1 sinken:
– u Blatt: klar;
– u Knoten nichtleerem linken Teilbaum:
linker Teilbaum steigt um eine Ebene auf.
Also beginnt Rebalancierung an v .
– Betrachte generell Knoten v mit der Eigenschaft, dass
die Tiefe eines Teilbaumes (o. B. d. A. des linken) um 1
gesunken ist.
. – Seite 344/726
1. Fall: Alter Wert bal(v) = 1.
Dann bal(v) := 0.
Die Tiefe von T (v) ist um 1 gesunken.
Rebalancierung am Elter von v fortsetzen.
Für ihn ist die Tiefe eines Teilbaumes um
genau 1 gesunken.
2. Fall: Alter Wert bal(v) = 0.
Dann bal(v) := −1.
Die Tiefe von T (v) ist unverändert.
Rebalancierung abgeschlossen.
. – Seite 345/726
3. Fall: Alter Wert bal(v) = −1, neuer Wert wäre −2.
1. Unterfall: D endet auf Ebene d.
Problem kommt
von außen.
bal(z) ∈ {0, −1}
Neue Situation:
v
z
w
A
d−2
d
B
C
D
2. Unterfall: D endet nicht auf Ebene d
(also auf Ebene d − 1).
Problem kommt
von innen.
bal(z) = 1
. – Seite 346/726
1. Unterfall, erste Variante:
−2
0
v 0
Linksrotation
z
an (v, z)
v
z
−1
A
d−2
d−1
A
B
C
C
B
d
Alter Wert bal(z) = 0: bal(z) := 0, bal(v) := −1.
Teilbaum B unverändert inklusive Balancegrad.
Neue Tiefe von z ist alte Tiefe von v .
Rebalancierung abgeschlossen.
. – Seite 347/726
1. Unterfall, zweite Variante:
−2
0
v −1
Linksrotation
z
an (v, z)
z
0
v
A
d−2
d−1
A
B
B
C
C
d
Alter Wert bal(z) = −1: bal(z) := 0, bal(v) := 0.
Teilbaum B unverändert inklusive Balancegrad.
Neue Tiefe von z ist alte Tiefe von v minus 1.
Rebalancierung am Elter fortsetzen.
. – Seite 348/726
2.Unterfall:
−2
0
v
Rechts-Links-
1
z
0
Rotation
w0
0
v
z
w
d−2
d−1
d
A
D
B
A
B
C
D
C
Neue Tiefe von w ist alte Tiefe von v minus 1:
−→ Rebalancierung am Elter fortsetzen.
Neue Balancewerte:
balalt (w) = 1 ⇒ bal(v) := 0, bal(w) := 0, bal(z) := −1.
balalt (w) = 0 ⇒ bal(v) := 0, bal(w) := 0, bal(z) := 0.
balalt (w) = −1 ⇒ bal(v) := 1, bal(w) := 0, bal(z) := 0.
. – Seite 349/726
2.Unterfall:
−2
0
v
Rechts-Links-
1
z
1
Rotation
w−1
0
v
z
w
d−2
d−1
d
C
A
C
D
A
B
D
B
Neue Tiefe von w ist alte Tiefe von v minus 1:
−→ Rebalancierung am Elter fortsetzen.
Neue Balancewerte:
balalt (w) = 1 ⇒ bal(v) := 0, bal(w) := 0, bal(z) := −1.
balalt (w) = 0 ⇒ bal(v) := 0, bal(w) := 0, bal(z) := 0.
balalt (w) = −1 ⇒ bal(v) := 1, bal(w) := 0, bal(z) := 0.
. – Seite 349/726
2.Unterfall:
−2
0
v
−1
d−2
d−1
d
Rechts-Links-
1
z
Rotation
w0
1
v
z
w
B
A
D
B
A
C
D
C
Neue Tiefe von w ist alte Tiefe von v minus 1:
−→ Rebalancierung am Elter fortsetzen.
Neue Balancewerte:
balalt (w) = 1 ⇒ bal(v) := 0, bal(w) := 0, bal(z) := −1.
balalt (w) = 0 ⇒ bal(v) := 0, bal(w) := 0, bal(z) := 0.
balalt (w) = −1 ⇒ bal(v) := 1, bal(w) := 0, bal(z) := 0.
. – Seite 349/726
Erkenntnisse für DELETE:
– Es kann mehrere (einfache oder doppelte) Rotationen
geben. Evtl. Suchpfad bis zur Wurzel zurück.
– Aufwand O(1) pro Knoten des Suchpfades:
Zeit O(log n) insgesamt.
Fazit:
– Zeit O(log n) für SEARCH, INSERT, DELETE und
– Speicherplatzausnutzung wie im normalen Suchbaum.
Aber: Komplexe Implementierung bei AVL-Bäumen und
2–3–Bäumen, viele Fallunterscheidungen.
Elegante, modernere Lösung mit Randomisierung.
. – Seite 351/726

Documents pareils