265 Algorithmen und Datenstrukturen 10 Binäre Suchbäume Suchbäume • Datenstruktur, die viele Operationen dynamischer Mengen unterstützt • Kann als Wörterbuch, aber auch zu mehr eingesetzt werden (Prioritätsschlange) • Aufwand der Grundoperationen proportional zur Höhe des Baumes ◦ vollständiger Binärbaum mit n Knoten: Worst-Case Θ(log n) ◦ lineare Kette aus n Knoten: Worst-Case Θ(n) • Verschiedene Typen von Suchbäumen: binäre Suchbäume, Rot-Schwarz-Bäume, B-Bäume 10 Binäre Suchbäume TU Bergakademie Freiberg, WS 2005/06 266 Algorithmen und Datenstrukturen 10.1 Binäre Suchbäume • Binärbaum dargestellt als verzeigerte Datenstruktur, jeder Knoten stellt ein Element dar. • root[T ] zeigt auf die Wurzel des Baumes T . • Jeder Knoten besitzt die Komponenten ◦ key: (plus evtl. weitere Nutzdaten) ◦ left: zeigt auf linken Sohn ◦ right: zeigt auf rechten Sohn ◦ p : zeigt auf Vater mit Ausnahme von p[root[T ]] = N IL. • Elemente müssen die binäre Suchbaumeigenschaft erfüllen: ◦ Liegt y im linken Teilbaum von x, so gilt key[y] ≤ key[x] ◦ Liegt y im rechten Teilbaum von x, so gilt key[y] ≥ key[x] 10.1 Binäre Suchbäume TU Bergakademie Freiberg, WS 2005/06 267 Algorithmen und Datenstrukturen Die binäre Suchbaumeigenschaft ermöglicht es, die Elemente eines im Knoten x wurzelnden Teilbaums in aufsteigender Reihenfolge auszugeben. Dies geschieht hier durch den rekursiven Algorithmus I NORDER -T REE -WALK. Funktionsweise: • Sicherstellen, dass x 6= N IL • Rekursiv Schlüssel im linken Teilbaum von x ausgeben • Schlüssel von x ausgeben • Rekursiv Schlüssel im rechten Teilbaum von x ausgeben • Analog: P REORDER -T REE -WALK (Wurzel zuerst), P OSTORDER -T REE -WALK (Wurzel zuletzt) 10.1 Binäre Suchbäume TU Bergakademie Freiberg, WS 2005/06 268 Algorithmen und Datenstrukturen I NORDER -T REE -WALK(x) if x 6= N IL then I NORDER -T REE -WALK(left[x]) key[x] ausgeben I NORDER -T REE -WALK(right[x]) Korrektheit: Folgt durch Induktion aus der binären Suchbaumeigenschaft. Aufwand: Durchlaufen erfordert Θ(n) Zeit (n = Anzahl Elemente im Baum), da jeder Knoten einmal besucht und ausgegeben wird. 10.1 Binäre Suchbäume TU Bergakademie Freiberg, WS 2005/06 269 Algorithmen und Datenstrukturen 10.2 Anfragen bei binären Suchbäumen 10.2.1 Suchen Zum Suchen eines Schlüssels k im binären Suchbaum T wende man folgenden Algorithmus an mit x = root[T ]: T REE -S EARCH(x, k) if x = N IL or k = key[x] then return x if k < key[x] then return T REE -S EARCH(left[x]) else return T REE -S EARCH(right[x]) Laufzeit: Algorithmus steigt rekursiv den Baum hinab, daher Laufzeit O(h) (h die Höhe des Baumes). 10.2 Anfragen bei binären Suchbäumen TU Bergakademie Freiberg, WS 2005/06 270 Algorithmen und Datenstrukturen Iterative Variante von T REE -S EARCH durch Ausrollen“ (unrolling) der ” Rekursion in eine while -Schleife: T REE -S EARCH -I TERATIVE(x, k) while x 6= N IL and k 6= key[x] do if k < key[x] then x ← left[x] else x ← right[x] return x Diese Variante ist auf den meisten Rechnern die schnellere. 10.2 Anfragen bei binären Suchbäumen TU Bergakademie Freiberg, WS 2005/06 271 Algorithmen und Datenstrukturen 10.2.2 Minimum und Maximum In einem binären Suchbaum sitzt das Element mit kleinstem Schlüssel im am weitesten links gelegenen Knoten, das größte im am weitesten rechts gelegenen. Man erreicht diese von der Wurzel aus durch Folgen der leftbzw. right-Zeiger in jedem Knoten bis man auf N IL trifft. T REE -M INIMUM(x) while left[x] 6= N IL do x ← left[x] return x T REE -M AXIMUM(x) while right[x] 6= N IL do x ← right[x] return x Laufzeit: Beide Algorithmen durchlaufen den Baum von der Wurzel bis zu einem Blatt, d.h. beide besitzen O(h) Laufzeit. 10.2 Anfragen bei binären Suchbäumen TU Bergakademie Freiberg, WS 2005/06 272 Algorithmen und Datenstrukturen 10.2.3 Vorgänger und Nachfolger Sind alle Schlüssel verschieden, so ist der Nachfolger eines Knoten x derjenige Knoten y mit dem kleinsten Schlüssel für den noch key[y] > key[x] gilt. Dieser kann (ohne Vergleiche) allein aus der Baumstruktur ermittelt werden. Besitzt x den größten Schlüssel in einem binären Suchbaum, so wird dessen Nachfolger zu N IL definiert. Zwei Fälle: 1. Ist der rechte Teilbaum von x nicht leer, so ist der Nachfolger von x das Minimum dieses Teilbaums. 2. Ist der rechte Teilbaum von x leer, beachte man: • Solange man von x ausgehend nach links im Baum aufsteigt, trifft man ausschließlich auf Schlüssel kleiner als der von x. • y ist genau dann der Nachfolger von x, wenn x der Vorgänger von y ist, d.h. wenn x das Maximum im linken Teilbaum von y ist. 10.2 Anfragen bei binären Suchbäumen TU Bergakademie Freiberg, WS 2005/06 273 Algorithmen und Datenstrukturen T REE -S UCCESSOR(x) if right[x] 6= N IL then return T REE -M INIMUM(right[x]) y ← p[x] while y 6= N IL and x = right[y] do x ← y y ← p[y] return y Übungsaufgabe: Ist y der Nachfolger von x und ist der rechte Teilbaum von x leer, so ist y derjenige Vorfahre maximaler Tiefe von x, dessen linker Sohn ebenfalls Vorfahre von x ist. T REE -P REDECESSOR bestimmt Vorgänger analog zu T REE -S UCCESSOR. Laufzeit: In beiden Fällen besuchen wir Knoten längs eines Weges im Baum entweder nach oben oder unten, daher Laufzeit O(h). 10.2 Anfragen bei binären Suchbäumen TU Bergakademie Freiberg, WS 2005/06 274 Algorithmen und Datenstrukturen 10.2.4 Einfügen und Löschen Bei diesen beiden Operationen muß ein binärer Suchbaum so modifiziert werden, dass die binäre Suchbaumeigenschaft erhalten bleibt. Einfügen des Schlüssels v: • Algorithmus T REE -I NSERT erhält Knoten z mit key[z] = v sowie left[z] = right[z] = N IL. • Mit Hilfe zweier Zeiger von der Wurzel aus den Baum absteigen ◦ Zeiger x: aktuelle Position beim Abstieg ◦ Zeiger y: dient zum Merken des Vaters von x • Jenachdem ob v größer oder kleiner als key[x] wird Abstieg bei linkem bzw. rechten Sohn von x fortgesetzt. • Einfügestelle erreicht sobald x = N IL; z wird linker/rechter Sohn von y jenachdem ob key[z] ≷ key[y] 10.2 Anfragen bei binären Suchbäumen TU Bergakademie Freiberg, WS 2005/06 Algorithmen und Datenstrukturen 275 T REE -I NSERT(T, z) 1 2 3 4 5 6 7 8 9 10 11 12 13 y ← N IL x ← root[T ] while x 6= N IL do y ← x if key[z] < key[x] then x ← left[x] else x ← right[x] p[z] ← y if y = N IL then root[T ] ← z else if key[z] < key[y] then left[y] ← z else right[y] ← z Laufzeit: O(h), wie bei T REE -S EARCH. 10.2 Anfragen bei binären Suchbäumen TU Bergakademie Freiberg, WS 2005/06 276 Algorithmen und Datenstrukturen Löschen eines Knotens z (Zeiger hierauf als Eingabe) 3 Fälle: Fall 1: z besitzt keine Söhne • Vater von z auf N IL anstelle von z zeigen lassen Fall 2: z besitzt einen Sohn • Vater von z auf Sohn von z anstelle von z zeigen lassen Fall 3: z besitzt 2 Söhne • Nachfolger y von z besitzt entweder keinen oder einen Sohn (y ist minimaler Knoten im rechten Teilbaum von z und besitzt keinen linken Sohn) • Knoten y löschen (fällt unter Fall 1 oder Fall 2) • Überschreibe Inhalt von z durch den von y 10.2 Anfragen bei binären Suchbäumen TU Bergakademie Freiberg, WS 2005/06 Algorithmen und Datenstrukturen 277 T REE -D ELETE(T, z) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 if left[z] = N IL oder right[z] = N IL then y ← z else y ← T REE -S UCCESSOR(z) if left[y] 6= N IL then x ← left[y] else x ← right[y] if x 6= N IL then p[x] ← p[y] if p[y] = N IL then root[T ] ← x else if y = left[p[y]] then left[p[y]] ← x else right[p[y]] ← x if y 6= z then Inhalt von z durch den von y überschreiben return y 10.2 Anfragen bei binären Suchbäumen TU Bergakademie Freiberg, WS 2005/06 278 Algorithmen und Datenstrukturen Laufzeit wieder O(h). Satz 10.1 Für einen binären Suchbaum der Höhe h besitzen die Grundoperationen I NSERT und D ELETE eine Laufzeit von O(h). Unschön: Komplexität bezüglich h, nicht n angegeben. Im ungünstigsten Fall ist aber h = Θ(n), nicht besser als verkettete Liste. Lösung: Geringe Höhe h = O(log2 n) garantieren (balancierte Bäume) Bäume können dadurch balanciert gehalten werden, dass sie bei Bedarf umstrukturiert werden. Dies erfordert zusätzlichen Aufwand bei I NSERT und D ELETE. Siehe red-black trees in [CLRS]. 10.2 Anfragen bei binären Suchbäumen TU Bergakademie Freiberg, WS 2005/06