Was bisher geschah rekursive Datenstrukturen: I lineare Datenstrukturen: Liste, Stack, Queue I hierarchische Datenstrukturen: Bäume I I I I I allgemeine Bäume Binäre Bäume Unäre Bäume = Listen Tiefe eines Knotens in t: Abstand (Kantenzahl) zur Wurzel Tiefe tiefe(t) des Baumes t: maximale Knotentiefe in t Größe size(t) des Baumes t: Anzahl aller Knoten in t Binäre Suchbäume: Binäre Bäume mit aufsteigend sortierter Inorder-Folge aller Schlüssel (Schlüsselwerte aus einer total geordneten Menge) Laufzeit für Suche, Einfügen, Löschen: O(tiefe(t)) AVL-Bäume (eingeschränkte Balanceeigenschaft): Binäre Bäume mit aufsteigend sortierter Inorder-Folge aller Schlüssel (Schlüsselwerte aus einer total geordneten Menge) Laufzeit für Suche, Einfügen, Löschen: O(log n) 153 Mehrweg-Suchbäume Suchbäume mit inneren Knoten verschiedener Knotengrade. I Knoten können mehrere Schlüssel enthalten I Knoten mit n ≥ 2 Schlüsseln (k1 , . . . , kn ) hat n + 1 Kinder (t0 , . . . , tn ). Suchbaumeigenschaft (für Mehrweg-Bäume): Jeder Schlüssel ist Separator zwischen Schlüsseln in den Kindern, d.h. für jeden Knoten u = Node(n, k , t) im Baum t gilt: I I I I Für alle im Teilbaum t0 vorkommenden Schlüssel v gilt v < k1 . Für alle i ∈ {1, . . . , n − 1} gilt: für alle im Teilbaum ti vorkommenden Schlüssel v gilt ki < v < ki+1 . Für alle im Teilbaum tn vorkommenden Schlüssel v gilt kn < v . 154 Datenstruktur Mehrweg-Suchbaum rekursive Datenstruktur Mehrweg-Suchbaum (MST): I I leerer Mehrweg-Suchbaum ⊥ (Blatt), innerer Knoten: Node (n, k , t) mit I I I Anzahl n ≥ 2 der Schlüssel Folge (k1 , . . . , kn ) der Schlüssel Folge (t0 , . . . , tn ) der Kinder (MST) 155 Inorder-Durchquerung von Mehrweg-Suchbäumen inorder(t) für MST t: I I falls t = ⊥: inorder(⊥) ← [] falls t = Node(n, k , t): I I I l ← inorder(t0 ) für alle i ← 1, . . . , n: l ← l ◦ [ki ] ◦ inorder(ti ) Ausgabe inorder(Node(n, k , t)) = l In jedem Mehrweg-Suchbaum bilden die Schlüssel in inorder-Reihenfolge eine aufsteigend sortierte Folge. 156 Suche in Mehrweg-Suchbäumen contains(t, e) für MST t und Wert e: I falls t = ⊥: contains(t, e) ← f I falls t = Node(n, k , t): finde Schlüssel oder Teilbaum-Index m: I I I m←0 solange km ≤ e: m ← m + 1 falls km = e: Ende mit contains(t, e) = t sonst contains(tm , e) (rekursiv) Laufzeit: O(tiefe(t)) 157 Beispiel B-Bäume zur Verwaltung großer Datenmengen Anwendungen bei Datenbanken Mehrweg-Suchbäume mit I Kinderzahl jedes Knotens zwischen m und 2m (für zuvor festgelegtes m) Ausnahme: Wurzel (darf weniger Kinder haben) I Alle Blätter haben denselben Abstand zur Wurzel. praktisch meist: I Knotengrad m sehr groß I Tiefe des Baumes sehr klein Optimierung: binäre Suche zum Finden der Schlüssel oder Teilbaum-Indizes m innerhalb eines Knotens 158 Spezialfall (2,4)-Bäume (2,4)-Baum: Mehrweg-Suchbaum mit Knoten mit 2, 3 oder 4 Kindern (B-Baum für m = 2) rekursive Datenstruktur ST24hElementi = I ⊥ I Node2 (ST24hElementi, Element, ST24hElementi) I Node3 (ST24hElementi, Element ST24hElementi, Element, ST24hElementi) I Node4 (ST24hElementi, Element ST24hElementi, Element, ST24hElementi, Element, ST24hElementi) 159 Einfügen in (2,4)-Bäume Suche der Einfüge-Position (Blatt) Fälle: 1. Einfügen in einen Knoten mit 2 oder 3 Kindern (2,4)-Baum-Eigenschaft nach Einfügen nicht verletzt 2. Einfügen in einen Knoten mit 4 Kindern (2,4)-Baum-Eigenschaft nach Einfügen evtl. verletzt, Verschiebung von Schlüsseln oder Teilung von Knoten notwendig 3. Einfügen als neuen Schlüssel im erreichten Knoten Idee: Beim Suchen der Einfüge-Position (Richtung: Wurzel → Blatt) vorsorglich alle 4-Knoten auf dem Pfad teilen. Einfügen des Elementes ist dann ohne zusätzliche Korrektur möglich. 160 Teilung von 4-Knoten 4-Knoten: Node4(t0 , x, t1 , y , t2 , z, t3 ) I in der Wurzel: Node4(t0 , x, t1 , y , t2 , z, t3 ) 7→ Node2(Node2(t0 , x, t1 ), y , Node2(t2 , z, t3 )) I als Kind eines 2-Knotens: Node2(Node4(t0 , x, t1 , y , t2 , z, t3 ), v , t4 ) 7→ Node3(Node2(t0 , x, t1 ), y , Node2(t2 , z, t3 ), v , t4 ) I als Kind eines 3-Knotens: Node3(Node4(t0 , x, t1 , y , t2 , z, t3 ), v , t4 , w, t5 ) 7→ Node4(Node2(t0 , x, t1 ), y , Node2(t2 , z, t3 ), v , t4 , w, t5 ) 161 Löschen aus (2,4)-Bäumen Löschen aus inneren Knoten: Ersetzen durch Inorder-Nachfolger (ggf. rekursiv)) Löschen aus Blättern: I Zu löschender Knoten ist Kind eines Knotens mit 3 oder 4 Kindern (2,4)-Baum-Eigenschaft nach Löschen nicht verletzt I Zu löschender Knoten ist Kind eines Knotens mit 2 Kindern (2,4)-Baum-Eigenschaft nach Löschen verletzt, Zusammenfügen notwendig Idee: Beim Suchen der Löschposition (Richtung: Wurzel → Blatt) vorsorglich geeignete Schlüsselverschiebungen (von Nachbarknoten) und Verschmelzungen. 162 Rot-Schwarz-Bäume Idee: Darstellung von (2, 4)-Bäumen als binäre Bäume Darstellung aller Schlüssel eines Knotens als Binärbaum (rote Kanten) Eigenschaften: I nie zwei rote Kanten nacheinander I Schwarz-Tiefe: log n I Tiefe: ≤ 2 log n I Suche wie in binären Bäumen I Einfügen und Löschen von 2-4-Bäumen „übersetzt“ I evtl. Rotationen (roter Kanten) notwendig Node(x, Node(y , t1 , t2 ), t3 ) 7→ Node(y , t1 , Node(x, t2 , t3 )) 163