www.mathematik-netz.de © Copyright, Page 1 of 8 AVL-Baum 1. Motivation und Einleitung Das Suchen, Einfügen und entfernen eines Schlüssels in einem zufällige erzeugten binären Suchbaum mit N Schlüsseln ist zwar im Mittel in O(log2 N) Schritten ausführbar, im schlechtesten Fall kann jedoch ein Aufwand von der Ordnung Ω (N) zur Ausführung dieser Operation erforderlich sein, weil der gegebene Baum zu einer linearen Liste degeneriert. Um stets einen möglichst optimalen Suchbaum nach den jeweiligen Änderungen zu erhalten, wäre es erforderlich, stets eine Transformation zu einem ausgeglichenen Baum vorzunehmen, so dass keine Degeneration stattfinden kann. Das kann ggf. eine Änderung aller Knotenwerte mit sich bringen. Um diesen Aufwand zu verringern, führten die russischen Mathematiker Adelson-Velskii und Landis eine abgeschwächte Form für einen ausgeglichenen binären Baum ein, der nach ihnen benannt AVL-Baum heißt. In diesem Dokument werden Kenntnisse zu den Themen (binäre) Suchbäume und Grundlegendes zur Graphentheorie vorausgesetzt. 2. Grundlegende Definitionen und Beispiele Definition: Ein AVL-Baum (AVL Tree) ist ein binärer Such-Baum, bei dem sich für jeden Knoten die Höhe seiner Teilbäume höchstens um 1 differiert. , Entscheidender Unterschied zwischen „normalen“ binären Suchbäumen und AVL-Bäumen ist also, dass man mit Hilfe einer Balance-Bedingung verhindern will, dass die Bäume nicht zu einer Listen oder rechtbzw. linkslastigen Bäumen entarten. Um dies konkret formulieren zu können benötigen wir noch folgende Definition: Sei T ein binärer Suchbaum und v ein Knoten in T. Weiter sei TL der linke und TR der rechte Teilbaum des Knotens v. Die Balance in Knoten v ist der Wert , Beispiele: bal(v) = Höhe(TL) - Höhe(TR) www.mathematik-netz.de © Copyright, Page 2 of 8 Wir berechnen einige Balancewerte für den linken (AVL-)Baum: bal(5)=3-2=-1; bal(2)=1-2=-1; bal(8)=1; bal(3)=0; bal(4)=1. Wir sehen also, dass für Blätter p stets gilt bal(p)=0. Ansonsten gilt für AVL-Bäume stets |bal(v)| ≤ 1. Nun berechnen wir im Gegensatz dazu einige Werte des rechten Baumes: bal(7)=3-1=2; bal(2)=-1. , Nun sind wir in die Lage versetzt die erste Definition eines AVL-Baumes zu konkretisieren. Definition: Ein AVL-Baum (AVL Tree) ist ein binärer Such-Baum T, so dass für für jeden Knoten v aus T gilt: , bal(v) ∈ {1,-1,0} Falls durch Einfüge- oder Löschoperationen die geforderte Balancebedingung |bal(v)| ≤ 1 (Strukturinvariante) verletzt wird, so muss sie durch eine Rebalancieroperation wiederhergestellt werden. Diese Operation manipulieren jeweils einige Knoten in der Nähe der Wurzel eines aus der Balance geratenen Teilbaumes, um den einen Teilbaum etwas anzuheben, den anderen abzusenken, und so eine Angleichung der Höhen zu erreichen. Man beachte, dass bei der Manipulation der Knoten nur Bewegungen in vertikaler Richtung erlaubt sind, während die relativen horizontalen Positionen der gezeigten Knoten und Teilbäume unverändert bleiben müssen. Der AVL-Baum kann zu einer Liste entarten, wenn dieser nur zwei Elemente enthält. Rekursiver Algorithmus der testet, ob das Balance-Kriterium erfüllt ist: algorithm isbalanced(T: tree):bool begin IF isempty(t) THEN Return true; ELSE Return [isbalanced(T.left) and isbalanced(T.right) and |height(t.left)-height(t.right)|<=1] FI end; Die Höhe eines leeren Baumes ist 0. Die Höhe eines Baumes mit nur einem Knoten ist 1. Bei allen anderen Bäumen ist die Höhe um 1 größer als die des höheren Unterbaumes. 3. Operationen auf AVL-Bäumen Da AVL-Bäume insbesondere binäre Suchbäume sind, kann man in ihnen nach einem Schlüssel genauso suchen wie in einem natürlichen Baum. Dazu folgt man im schlechtesten Fall einem Pfad von der Wurzel bis zu einem Blatt. Weil die Höhe durch die Invariante (Balanciertheit) logarithmisch beschränkt bleibt, ist klar, dass man in einem AVL-Baum mit N Schlüsseln in höchstens O(log(N)) Schritten einen Schlüssel wiederfinden kann bzw. feststellen kann, dass ein Schlüssel im Baum nicht vorkommt. Um einen Schlüssel in einem AVL-Baum einzufügen, sucht man zunächst nach dem Schlüssel im Baum. Wenn der einzufügende Schlüssel noch nicht im Baum vorkommt, endet die Suche im Blatt, das die erwartete Position des Schlüssels repräsentiert. Man fügt den Schlüssel dort ein, wie im Falle natürlicher Bäume. Erkennbar ist, dass sich beim Einhängen eines Elementes in den Baum evtl. Probleme ergeben. Durch das Einhängen eines Elementes unterhalb einer (Teil)- Wurzel kann im linken oder rechten www.mathematik-netz.de © Copyright, Page 3 of 8 Teilbaum ein Ungleichgewicht entstehen. Wir können (zu Recht) davon ausgehen, dass es keine Rolle spielt, ob die Eintragung im rechten oder linken Teilbaum passiert. Skizze: Situation direkt nach dem Einfügen eines Schlüssels (links) und nach Wiederherstellung der Balance (rechts) Alle drei Operationen (insert, member und delete) benötigen O(log n) Zeit und O(n) Speicherplatz im worst case. www.mathematik-netz.de © Copyright, Page 4 of 8 Durch Einfügen eines neuen Knotens als rechten oder linken Sohn eines Knotens p wird p ein Knoten mit Balancefaktor -1 oder +1, und die Höhe des Teilbaums mit Wurzel p wächst um 1. Wir rufen daher eine spezielle Prozedur für den Knoten p auf, die den Suchpfad zurückläuft, die Balancefaktoren prüft, gegebenenfalls adjustiert und Umstrukturierungen veranlasst, die sicherstellen, dass für alle Knoten die Höhendifferenz der jeweils zugehörigen Teilbäume wieder höchstens 1 sind. Beim Einfügen können grundsätzlich insgesamt 4 verschiedene Situationen auftreten. Wir verdeutlichen dies an konkreten Beispielen die der Allgemeinheit jedoch nicht abträglich sind. Im Folgenden sind die einzelnen Fälle durch Skizzen eines AVL-Baumes angedeutet, dabei stellt die erste Grafik die Situation nach dem Einfügen eines Schlüsselwertes dar, so dass es zu einer Rebalancierungsoperation kommen muss. Dies ist bereits mit einem Pfeil angedeutet. 1.Fall: Einfache Rechts-Rotation Nach dem Einfügen der Zahl 5 überprüft der Algorithmus die Knoten, ob diese die Balance-Bedingung erfüllen – dabei berechnet der Algorithmus alle Balance-Werte vom eingefügten Element ausgehend zurück zum Wurzelknoten. Dabei ergeben sich also: bal(10) = -2 und bal(7) = -1. Der Knoten 10 ist, nach dem Einfügen des Knotens mit Schlüsselwert 5, aus der Balance geraten. Deshalb muss eine einfache Rotation entgegen der Lastigkeit durchgefürt werden, also eine Rechtsrotation. 2.Fall: Einfache Links-Rotation Nach dem Einfügen der Zahl 15 überprüft der Algorithmus die Knoten, ob diese die Balance-Bedingung erfüllen – dabei berechnet der Algorithmus alle Balance-Werte vom eingefügten Element ausgehend zurück zum Wurzelknoten. Dabei ergeben sich also: bal(10) = 2 und bal(7) = 1. Der Knoten 10 ist, nach dem Einfügen des Knotens mit Schlüsselwert 15, aus der Balance geraten. Deshalb muss eine einfache Rotation entgegen der Lastigkeit durchgefürt werden, also eine Linksrotation. www.mathematik-netz.de © Copyright, Page 5 of 8 3.Fall: Doppelte Rechts-/Links-Rotation Nach dem Einfügen der Zahl 12 überprüft der Algorithmus die Knoten, ob diese die Balance-Bedingung erfüllen – dabei berechnet der Algorithmus alle Balance-Werte vom eingefügten Element ausgehend zurück zum Wurzelknoten. Dabei ergeben sich also: bal(10) = 2 und bal(15) = -1. Der Knoten 10 ist, nach dem Einfügen des Knotens mit Schlüsselwert 15, aus der Balance geraten. Deshalb muss eine Doppel-Rotation (Rechts/Links) durchgeführt werden. Die Doppelrotation setzt sich, wie der Name bereits vermuten lässt, aus zwei einfachen Rotationen zusammen. Durch die erste RechtsRotation entsteht Fall 2 – anschließend ist die Lösung kein Problem mehr. 4.Fall: Doppelte Links-/Rechts-Rotation Nach dem Einfügen der Zahl 7 überprüft der Algorithmus die Knoten, ob diese die Balance-Bedingung erfüllen – dabei berechnet der Algorithmus alle Balance-Werte vom eingefügten Element ausgehend zurück zum Wurzelknoten. Dabei ergeben sich also: bal(10) = -2 und bal(5) = 1. Der Knoten 10 ist, nach dem Einfügen des Knotens mit Schlüsselwert 7, aus der Balance geraten. Deshalb muss eine Doppel-Rotation (Links/Rechts) durchgeführt werden. Die Doppelrotation setzt sich, wie der Name bereits vermuten lässt, aus zwei einfachen Rotationen zusammen. Durch die erste Links-Rotation entsteht Fall 1 – anschließend ist die Lösung kein Problem mehr. Die eben gemachten Fallunterscheidungen werden sich als überaus nützlich erweisen, denn diese entsprechen den elementaren Bausteinen einer jeden Rebalancierungsoperation. Wir werden dies an folgendem Beispiel verdeutlichen. www.mathematik-netz.de © Copyright, Page 6 of 8 Welche Rotation wann ablaufen muss ist einfach zu beantworten: Hat der aus der Balance geratenen Knoten ein differentes Vorzeichen im Vergleich mit seinem (auf dem Suchpfad befindlichem) Sohn, so muss eine Doppelrotation erfolgen. Ansonsten genügt eine einfache Rotation. Grafisch erkennt man eine Doppelrotation also an einem Knick im Suchpfad, dagegen ist eine einfache Rotation stets dann notwendig, wenn der Suchpfad eine gerade Strecke bildet. Beispiel: Gegeben ist skizzierter AVL-Baum. Fügen wir in diesen noch den Schlüsselwert 14 ein, so gerät dieser Baum aus der Balance. Rot hervorgehoben ist der Suchpfad zur prädestinierten Einfügeposition des Schlüsselwertes 14. Für alle Knoten auf diesem Pfad berechnet eine spezielle Prozedur die Balancefaktoren: bal(9)= -2, bal(15)=1 – da die Knoten jeweils unterschiedliche Vorzeichen haben ist also eine Doppelrotation vorzunehmen. Da der Suchpfad visuell hervorgehoben ist kann man dies schön am Knick erkennen. www.mathematik-netz.de © Copyright, Page 7 of 8 Wir identifizieren nun die (markierten) Knoten mit den Schlüsselwerten 9, 15 und 12 mit denen im Fall 3. Dadurch erhalten wir durch Beibehaltung der Reihenfolge der einzelnen Teilbäume und stellenweises Umhängen einzelner Knoten folgenden ausgeglichenen Baum: Beachten Sie dabei bitte, dass die Teilbäume unberührt bleiben – es kann lediglich erforderlich sein einzelne Zweige umzuhängen, so dass die Suchbaumeigenschaft erhalten bleibt. , Die Situation in obigem Beispiel kann man auch allgemein skizzieren: Entsprechend auch das Prinzip der kleinen www.mathematik-netz.de © Copyright, Page 8 of 8 Man kann sehr schön erkennen, dass die Reihenfolge der Teilbäume X, Y, Z oder A, B1, B2, C erhalten bleibt. Lediglich die Zuordnungen können und müssen sich dann auch ändern. Löschoperationen werden wir hier nicht mehr im Einzelnen behandeln. Letztlich kann man nach Entfernen des jeweiligen Eintrages alle Unausgewogenheiten auf die bereits beim Einfügen besprochenen Fälle zurückfühen.