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