Programmiersprachen II Fortsetzung Datenstrukturen Balancierte Bume 2 Prof
Programmiersprachen II Fortsetzung Datenstrukturen Balancierte Bäume 2 Prof. Dr. Reiner Güttler Fachbereich GIS HTW
3. 1. 2 Red-Black-Trees andere Form von höhenbalancierten Bäumen rot/schwarz hat keine wirkliche Bedeutung, leicht/schwer, yin/yang oder positiv/negativ ginge auch. In der Anwendung zur Veranschaulichung spiegelt jeweils der Rand! die Farbe wieder bzgl. red/black, nicht die Füllfarbe. Wichtiger Unterschied zu AVL-Trees: hier wird schon während des Einfügens bzw. Löschens eines Knotens rebalanciert
Definition der red/black-Regeln: 1. Jeder Knoten ist rot oder schwarz. 2. Die Wurzel ist immer schwarz. 3. Ist ein Knoten rot, so sind seine Söhne schwarz (Achtung: gilt nicht umgekehrt). 4. Jeder Pfad von der Wurzel zu einem Blatt enthält die gleiche Anzahl von schwarzen Knoten. 5. Alternativ zu 4: jeder Pfad von einem Knoten zu einem der Blätter seiner Unterbäume enthält die gleiche Anzahl an schwarzen Knoten. Bem. 5. sagt aus, dass 4. für jeden Unterbaum gilt.
Definition: Die Höhe eines Baums wird definiert durch das maximale Level eines Knotens. Die Anzahl der schwarzen Knoten auf einem Pfad von Wurzel zu Blatt heisst „black-Höhe“. Beobachtung: Für die Höhe h eines red-black trees mit n internen Knoten gilt h <= 2 log (n+1). (kann mathematisch bewiesen werden!). Was bedeutet das?
Folge: Die Funktionen insert() und delete() laufen in O(log n), d. h. der Baum ist „einigermassen“ balanciert. Wie bei AVL-trees können aber insert()- und delete()-Operationen die Balanceregeln verletzen, d. h. es müssen Operationen ausgeführt werden, um die Balance aufrecht zu erhalten.
Zur Verfügung stehende Operationen: rb(), ändert die Farbe eines Knotens, d. h. macht einen roten schwarz und einen schwarzen rot. flip() findet nur Anwendung auf einen schwarzen Knoten mit 2 roten Söhnen. Der Knoten wird rot, die Söhne schwarz. (Dies sind 3 rb() in einem, die Funktion kann prinzipiell auch wegfallen). ror() angewandt auf einen Knoten führt eine Rechtsrotation durch. rol() angewandt auf einen Knoten führt eine Linksrotation durch.
Experimente jeweils mit Verfolgung der red/black-Regeln: 1. Folge 50, 25, 75. Dann insert(irgendwas)=> flip() notwendig. 2. 50, 25, 75, bzw. 50, 25, 35: Rotationen, Doppelrotation, inside child, outside child 3. 50, 25, 75, 12, 6 4. Wie „unbalanciert“ kann ein red/black-tree werden? Dazu 50, 60, 70, 80, 90, 65, 75, 85, 95 5. insert(): 50, 25, 75, 12, 6, rb(Vater), rb(Grossvater), dann Rotation 6. insert(): 50, 25, 75, 12, 18, rb(Knoten selbst), rb(Grossvater), dann Doppelrotation
Genauere Betrachtung: Wie wirken sich die Operationen aus? 1. flip(): flip() lässt die black-Höhe unverändert macht eine Verletzung von Regel 3 durch insert() am Blatt unwahrscheinlicher (wird noch genauer definiert) führt evtl. zu Verletzung von Regel 3 oberhalb: kann aber mit einer Rotation bzw. Doppelrotation verbunden mit rb() korrigiert werden (siehe bei 3. )
2. Rotationen nach erfolgtem insert(): Sei x der eingefügte Knoten (immer rot!), P sein Vater, G sein „Grossvater“ Es gibt 4 Möglichkeiten: G P G G G P P x x a) b) P x c) x d) Wie die Situation bzgl. der red/black-Regeln ist, hängt von den jeweiligen Farben ab.
Erstaunlicherweise gibt es nur 3 grundsätzliche Fälle (wg. Symmetrie und da x immer! rot ist): 1. P ist schwarz. 2. P ist rot und x ist ein „Aussenenkel“, a) und c). 3. P ist rot und x ist ein „Innenenkel“, b) und d). Fall 1: P ist schwarz. Hier ist nichts zu tun, einfach insert() durchführen. Die evtl. erfolgten Operationen auf dem Weg von der Wurzel bis zu P haben dafür gesorgt, dass oberhalb alles „in Ordnung ist“.
Fall 2: P ist rot, x ist Aussenenkel. (G muss schwarz sein!) rb(P), rb(G) und eine Rechtsrotation (Fall a)) bzw. Linksrotation (Fall c)) um G. Fall 3: P ist rot, x ist Innenenkel. (G muss schwarz sein!) rb(x), rb(G) und eine Linksrotation um P sowie Rechtsrotation um G (Fall b)) bzw. Rechtsrotation um P und Linksrotation um G (Fall d)). Andere Möglichkeiten?
x hat einen Bruder y. Ist P schwarz, kein Problem. Ist P rot, dann müsste y schwarz sein. Dann wäre aber Regel 4 verletzt. P kann also nicht rot sein und ein schwarzes Kind haben. P hat einen Bruder u. Ist P schwarz, kein Problem, nichts zu tun. Ist P rot, dann müsste u auch rot sein. Dann hätte aber bei G ein flip() stattgefunden, der Fall kann also nicht auftreten.
3. Rotationen auf dem Weg zu P können auf Grund von flip()Operationen auftreten (siehe Betrachtung von flip()). 2 Möglichkeiten wie in den Fällen 2 und 3, je nachdem, ob der Verursacher Aussenenkel oder Innenenkel ist (Unterbäume, die an x, P oder G hängen werden von Rotationen nicht berührt!) 3 a) Betrachte die Folge: 50, 25, 75, 12, 37, 6, 18. Dabei flip()Operationen bei 12 und 6. Jetzt: insert(3). erfordert flip(12) Führt zu Verletzung von Regel 3. Lösung: exakt wie bei Fall 2.
3 b) Betrachte die Folge 50, 25, 75, 12, 37, 31, 43. Dabei flip()-Operationen bei 12 und 31. Jetzt: insert(28). erfordert flip(37) Führt zu Verletzung von Regel 3. Lösung: exakt wie bei Fall 3. Bem. Die notwendigen Operationen bei delete() sind etwas komplexer. Sie werden hier nicht betrachtet, da sie keine grundsätzlich neuen Erkenntnisse bringen.
Fazit für red/black-Trees: Alle Grundoperationen (insert(), find(), delete()) laufen in O(log n). Dies gilt auch für „vorsortierte“ Folgen. Im Vergleich zu AVL-Trees sind weniger Operationen nach insert() notwendig. Auch insgesamt, d, h, inkl. der Operationen vor insert() sind red/black-Trees effizienter. Grund sind die vorbereitenden flip()Operationen (kann mathematisch bewiesen werden!). Red/black-Trees funktionieren auch ohne flip()-Operationen. Die Einbussen an Effizienz wirken sich nicht! auf die Grössenordnung (O()-Schreibweise) aus. Bei Implementierungen genügt es, die Operationen zu implementieren. Die black-Höhe muss nicht mit implementiert werden, da die Operationen die Korrektheit von Regel 4 automatisch mit erfüllen.
- Slides: 15