Die AVL-Eigenschaft soll bei Einfügungen und Streichungen erhalten bleiben. Dafür gibt es zwei mögliche Operationen: 0 -2 Rotation y -1 x 0 x y T3 T1 T1 T2 T2 T3 Abbildung 3.10: Rotation nach rechts (analog links) 0 -2 Doppelrotation z +1 x ±1 T1 T4 y T2 y 0/-1 +1/0 x z T1 T2 T3 T4 T3 Abbildung 3.11: Doppelrotation links-rechts (analog rechts-links) Falls die Unterbäume AVL-Eigenschaft haben, ist der Baum nach den entprechenden Operationen auch wieder ein AVL-Baum. Damit gestaltet sich Einfügen bzw. Streichen wie beim einfachen binären Suchbaum, falls notwendig müssen zusätzlich Rotationen oder Doppelrotationen durchgeführt werden, und zwar entlang des Pfades zum eingefügten bzw. gestrichenen Element (nur da kann eine Veränderung der AVL-Eigenschaft auftreten). Alle Wörterbuchoperationen benötigen also O(log n) Zeit auch im schlechtesten Fall (Rotation bzw. Doppelrotation besteht nur aus dem Umhängen von Zeigern, was konstante Zeit kostet). 3.1.5 (a,b)-Bäume (a,b)-Bäume sind eine Datenstruktur für das Wörterbuchproblem und im allgemeinen keine binären Suchbäume. a, b ∈ N Definition 3.1.5. (a,b)-Baum Sei ρ(v) = Anzahl der Kinder eines Knoten v. Seien a, b ∈ N, a ≥ 2, b ≥ 2a − 1 43 Ein Baum B heißt (a,b)-Baum genau dann wenn gilt: • Alle Blätter haben die gleiche Tiefe, • für alle inneren Knoten v gilt: ρ(v) ≤ b, • für alle inneren Knoten v (außer der Wurzel) gilt: ρ(v) ≥ a, • für die Wurzel w gilt: ρ(w) ≥ 2. Der kleinstmögliche (a,b)-Baum ist ein (2,3)-Baum. Höhe vom (a,b)-Baum: Nun schätzen wir die Höhe eines (a,b)-Baums ab. Sei n die Anzahl der Blätter eines (a,b)-Baums der Höhe h. Ein Baum der Höhe h hat die meisten Blätter, wenn jeder Knoten b Kinder hat. Die wenigsten Blätter hat er, wenn die Wurzel zwei und jeder andere Knoten a Kinder hat. Also gilt: 2ah−1 ≤ n ≤ bh (h − 1) log a ≤ log n ≤ h log b Somit hat ein (a,b)-Baum mit n Blättern die Höhe h = Θ(log n) Das bedeutet für einen Baum mit einer Million Blättern und b etwa gleich 100 eine Höhe von nur drei bis vier. Wir betrachten die Abspeicherung einer Menge von Daten S ⊂ U (U , ≤ (linear geordnet)) mit S = x1 , ..., xn und x1 < x2 < ... < xn von einem (a,b)-Baum mit n Blättern. Daraus ergeben sich folgende Eigenschaften: 1. Die Elemente stehen in den Blättern und zwar aufsteigend geordnet von links nach rechts. 2. In jedem inneren Knoten v mit k = ρ(v) − 1 sind die Elemente y1 bis yk aufsteigend geordnet. 3. In den inneren Knoten verweisen Zeiger auf Teilbäume, wobei yi das größte Element in den Blättern im i-ten Teilbaum des Knotens v ist, für i = 1 bis k. (siehe Abbildung 3.12) Es folgt ein Beispiel, bei dem die Wochentage in einem (2,3)-Baum abgelegt sind. Dann werden zwei weitere Tage eingefügt. Der A-Tag und der E-Tag. (siehe Abbildung 3.13 bis 3.17) Wörterbuchoperationen: Wir betrachten nun die Wörterbuchoperationen zum Suchen, Einfügen und Streichen. 44 y1 y2 v y1 ... yk y2 >yk yk Abbildung 3.12: (a,b)-Baum Do Mo Di Di Fr Mi Do Fr Sa Mi Mo Sa So Abbildung 3.13: Bsp.: Wochentage im (2,3)-Baum aufsteigend geordnet Do Fr At Di At Di Fr Mi Do Fr Mi Sa Mo Sa So Abbildung 3.14: Als einfacher Fall der Einfügung wird der A-Tag eingefügt. Do Mo At Di At Di Et Do Et Fr Mi Fr Mi Mo Sa Sa So Abbildung 3.15: Als nächstes Beispiel wird ein E-Tag eingefügt. 45 Do Fr Mo Et At Di At Di Do Et Mi Fr Sa Mi Mo Sa So Abbildung 3.16: Der Knoten mit (Et Fr Mi) wird aufgespalten und Fr rückt nach oben. Fr Do At Di At Di Mo Et Do Et Mi Fr Mi Sa Mo Sa So Abbildung 3.17: Die Wurzel wird aufgespalten und aus Fr wird eine neue Wurzel erzeugt. Algorithmus zum Suchen: SUCH(x) 1. Sei y1 ...yk die Beschriftung der Wurzel, finde i mit yi−1 < x ≤ yi bzw. i = 1, falls x ≤ y1 oder i = k + 1, falls x > yk . 2. Suche rekursiv im i-ten Teilbaum. 3. Falls beim Blatt angelangt: Ist die Beschriftung = x, dann wurde x gefunden. Ist die Beschriftung 6= x, dann ist x nicht in der Menge S enthalten. Algorithmus zum Einfügen: EINF(x) 1. SUCH(x) liefert ein Blatt w. 2. Falls w das Element x enthält, dann sind wir fertig. Sonst schaffe ein neues Blatt, und hänge es links von w am Vaterknoten v von w an und füge x an entsprechender Stelle in v ein. Sind wir bei dem rechtesten Blatt angelangt, dann müssen wir noch mal vergleichen um herauszufinden, ob wir rechts oder links einfügen sollen. 46 3. Falls immer noch ρ(v) ≤ b ist, dann sind wir fertig. Sonst (ρ(v) = b + 1): Spalte v in zwei Knoten v 0 , v 00 mit . . . zm zm+1 . . . v T1 y1 . . . yk 2 und . . . zm v' Tk+1 b+1 Ts 2 Kindern. ys+1 zm+1 . . . y1 . . . ys T1 b+1 ys+2 . . . yk Ts+1 Ts+2 v'' Tk+1 Es kann auch sein, dass zm+1 der linkeste oder zm der rechteste Eintrag im Vaterknoten ist. 4. Wende Schritt 3 auf den Vater von v an... usw. ggf. bis zur Wurzel. 5. Falls die Wurzel gespalten werden muss, schaffe eine neue Wurzel mit zwei Kindern, die die beiden Teile der alten Wurzel als Kinder hat. Dabei müssen immer Schlüssel in den inneren Knoten aktualisiert werden. Der Algorithmus benötigt O(log n) Zeit, da von der Wurzel zum Blatt und eventuell wieder zurückgegangen werden muss. Spalten kostet konstante Zeit, da nur die Zeiger umgehängt werden. 47