Algorithmen und Datenstrukturen Übung 6. Rot-Schwarz-Bäume Top-Down 2.-3-4-Bäume Zum Ausschluß des ungünstigsten Falls bei binären Suchbäumen ist eine gewisse Flexibilität in den verwendeten Datenstrukturen nötig. Das kann bspw. durch Aufnahme von mehr als einem Schlüssel in Baumknoten erreicht werden. So soll es 3-Knoten bzw. 4-Knoten geben, die 2 bzw. 3 Schlüssel enthalten können: - Ein 3-Knoten besitzt 3 von ihm ausgehende Verkettungen -- eine für alle Datensätze mit Schlüsseln, die kleiner sind als seine beiden Schlüssel -- eine für alle Datensätze, die zwischen den beiden Schlüsseln liegen -- eine für alle Datensätze mit Schlüsseln, die größer sind als seine beiden Schlüssel. - Ein 4-Knoten besitzt vier von ihm ausgehende Verkettungen, nämlich eine Verkettung für jedes der Intervalle, die durch seine drei Schlüssel definiert werden. Rot-Schwarz-Bäume Es ist möglich 2-3-4-Bäume als gewöhnliche binäre Bäume (mit nur zwei Knoten) darzustellen, wobei nur ein zusätzliches Bit je Knoten verwendet wird. Die Idee besteht darin, 3-Knoten und 4-Knoten als kleine binäre Bäume darzustellen, die durch „rote“ Verkettungen miteinander verbunden sind, im Gegensatz zu den schwarzen Verkettungen, die den 2-3-4-Baum zusammenhalten: oder Abb.: Rot-schwarze Darstellung von Bäumen 4-Knoten werden als 2-Knoten dargestellt, die mittels einer roten Verkettung verbunden sind. 3-Knoten werden als zwei –Knoten dargestellt, die mit einer roten Markierung verbunden sind. Zu jedem 2-3-4-Baum gibt es viele ihm entsprechende Rot-Schwarz-Bäume. 1 Algorithmen und Datenstrukturen Eine Variante von Rot-schwarz-Bäumen Nach jeder Einfüge-Operation bzw. Entferne-Operation lassen sich Rot-Scwarz-Bäume durch Rotationen ausgleichen. Eine Variante von Rot-Schwarz-Bäumen ist durch folgende Farbeigenschaften definiert: 1. Jeder Knoten ist entweder rot oder schwarz gefärbt. 2. der Wurzelknoten ist schwarz gefärbt. 3. Falls ein Knoten rot gefärbt ist, müssen seine Nachfolger schwarz gefärbt sein. 4. Jeder Pfad von einem Knoten zu einer „Null-Referenz“ muß die gleiche Anzahl von schwarzen Knoten enthalten. Eine Folgerung dieser Farbregeln ist: Die Höhe eines Rot-Schwarz-Baums ist etwa 2 log( N 1) . Aufgabe: Ermittle, welche Gestalt jeweils ein nach den vorliegenden Farbregeln erstellte Rot-SchwarzBaum beim einfügen folgenden Schlüssel „10 85 15 70 20 60 30 50 65 80 90 40 5 55“ annimmt 10 10 85 10 85 15 15 10 85 70 15 10 85 70 20 15 10 70 20 85 60 15 10 70 20 85 60 2 Algorithmen und Datenstrukturen 30 15 10 70 30 85 20 60 50 30 15 10 70 20 60 85 50 65 30 15 10 70 20 60 85 50 65 80 30 15 10 70 20 60 85 50 65 80 90 30 15 10 70 20 60 85 50 65 3 80 90 Algorithmen und Datenstrukturen 40 30 15 70 10 20 60 85 50 65 80 90 40 5 30 15 70 10 20 60 5 85 50 65 80 90 40 55 30 15 70 10 20 60 5 85 50 40 65 9 85 55 80 90 Die Abbildungen zeigen, daß im durchschnitt der Rot-Schwarz-Baum ungefähr die Tiefe eines AVLBaums besitzt. Der Vorteil von Rot-Schwarz-Bäumen ist der geringere Overhead zur Ausführung von Einfügevorgängen und die geringere Anzahl von Rotationen. „Top-Down“ Rot-Schwarz-Bäume Kann auf dem Weg nach unten festgestellt werden, daß ein Knoten X zwei rote Nachfolgeknoten hat, dann wird X rot und die beiden „Kinder“ schwarz: X c1 X c2 c1 c2 Das führt zu einem Verstoß gegen Bedingung 3, falls der Vorgänger von X auch rot ist. In diesem Fall können aber geeignete Rotationen herangezogen werden: 4 Algorithmen und Datenstrukturen G P P S X C X A G A B B S C G P X S X P G C A A B1 B1 B2 B2 S C Der folgende Fall kann nicht eintreten: Der Nachbar vom Elternknoten ist rot gefärbt. Auf dem Weg nach unten muß der Knoten mit zwei roten Nachfolgern einen schwarzen Großvaterknoten haben. Implementierung Sie wird dadurch erschwert, daß einige Teilbäume (z.B. der rechte teilbaum des Knoten 10 im vorliegenden Bsp.) leer sein können, und die Wurzel des baums (, da ohne Vorgänger, ) einer speziellen Behandlung bedarf. Aus diesem Grund werden hier „Sentinel“-Knoten verwendet: - eine für die Wurzel. Dieser Knoten speichert den Schlüssel und einen rechten Link zu dem realen Knoten - einen Nullknoten (nullNode), der eine Null-Referenz anzeigt. Der Inorder-Durchlauf nimmt aus diesem Grund folgende Gestalt an: /* Ausgabe der im Baum gespeicherten Datenelemente in sortierter Reihenfolge. */ public void printTree( ) { if( isEmpty() ) System.out.println("Leerer Baum"); else printTree( header.rechts ); } /* * Interne Methode fuer die Ausgabe des Baum in sortierter Reihenfolge. * b ist der Wurzelknoten. */ private void printTree(RotSchwarzKnoten b) { if (b != nullNode ) { printTree(b.links); System.out.println(b.daten ); printTree(b.rechts ); } } 5