Menu
Coddy logo textTech

AVL-Baum

Zuletzt aktualisiert

Ein AVL-Baum ist ein selbstausgleichender binärer Suchbaum. Er funktioniert wie ein normaler BST, prüft aber nach jeder Einfügung den Balancefaktor jedes Vorfahren - den Höhenunterschied zwischen seinem linken und rechten Teilbaum - und wenn ein Knoten unausgeglichen wird (ein Unterschied größer als 1), führt er Rotationen durch, um das Gleichgewicht wiederherzustellen. Drücken Sie oben auf Wiedergabe, um zu sehen, wie Werte eingefügt werden und sich der Baum wieder in Form dreht.

Da er den Baum nie mehr als nur leicht schief werden lässt, garantiert ein AVL-Baum eine Höhe von O(log n), sodass Suche, Einfügen und Löschen immer O(log n) sind - selbst bei sortierter Eingabe, die einen einfachen BST ruinieren würde. Der Preis dafür sind die zusätzlichen Rotationen und die Höhenverwaltung bei jeder Einfügung.

Zeit- und Speicherkomplexität

OperationKomplexitätHinweise
SucheO(log n)Die Höhe ist immer ~1.44 log n
EinfügenO(log n)Plus O(1) Rotationen
LöschenO(log n)Plus O(log n) Rotationen
SpeicherO(n)Ein Höhenfeld pro Knoten

Die vier Rotationsfälle

FallUngleichgewichtKorrektur
Links-LinksSchwer auf der linken Seite des linken KindesEine Rechtsrotation
Rechts-RechtsSchwer auf der rechten Seite des rechten KindesEine Linksrotation
Links-RechtsSchwer auf der rechten Seite des linken KindesLinks-, dann Rechtsrotation
Rechts-LinksSchwer auf der linken Seite des rechten KindesRechts-, dann Linksrotation

Durchgerechnetes Beispiel

Einfügen von [10, 20, 30, 40, 50, 25], einen Wert nach dem anderen:

SchrittStrukturAktion
10 einfügen10Der erste Knoten wird zur Wurzel; ausgeglichen
20 einfügen10(_, 20)Geht rechts von 10; weiterhin ausgeglichen
30 einfügen20(10, 30)Rechts-Rechts bei 10, also hebt eine Linksrotation 20 zur Wurzel
40 einfügen20(10, 30(_, 40))Geht rechts von 30; alle Balancefaktoren bleiben innerhalb von ±1
50 einfügen20(10, 40(30, 50))Rechts-Rechts bei 30, also hebt eine Linksrotation bei 30 den Knoten 40
25 einfügen30(20(10, 25), 40(_, 50))Rechts-Links bei 20: Teilbaum von 40 rechtsrotieren, dann 20 linksrotieren

Wann man einen AVL-Baum verwenden sollte

Verwenden, wennVermeiden, wenn
Suchvorgänge Einfügungen bei weitem überwiegen und Sie die kompakteste mögliche Höhe wollenEinfügungen und Löschungen dominieren - die zusätzlichen Rotationen und das Rebalancieren kosten mehr als bei einem Rot-Schwarz-Baum
Sie garantiert O(log n) im schlimmsten Fall benötigen, selbst bei feindlicher oder sortierter EingabeEine einfache Hash-Tabelle würde genügen - Sie brauchen keine geordnete Traversierung oder Bereichsabfragen
Sie geordnete Operationen benötigen: In-Order-Traversierung, Vorgänger/Nachfolger, BereichsabfragenDer Datensatz winzig ist - ein einfacher BST oder ein sortiertes Array ist einfacher und schnell genug
Daten möglicherweise bereits sortiert ankommen, was einen unausgeglichenen BST in eine verkettete Liste verwandeln würdeSie sich den zusätzlichen Speicher des Höhenfeldes pro Knoten in einem sehr engen Speicherbudget nicht leisten können

AVL Tree-Code

Eine saubere, lauffähige AVL Tree-Implementierung in Python, JavaScript, Java, C++, C. Wähle eine Sprache, kopiere den Code oder öffne ihn vorgeladen im Coddy-Playground.

AVL Tree-Code in Python

Python
1class Node:2    def __init__(self, key):3        self.key = key4        self.left = None5        self.right = None6        self.height = 17
8
9def height(node):10    return node.height if node else 011
12
13def update(node):14    node.height = 1 + max(height(node.left), height(node.right))15
16
17def rotate_right(y):18    x = y.left19    y.left = x.right20    x.right = y21    update(y)22    update(x)23    return x24
25
26def rotate_left(x):27    y = x.right28    x.right = y.left29    y.left = x30    update(x)31    update(y)32    return y33
34
35def insert(node, key):36    if node is None:37        return Node(key)38    if key < node.key:39        node.left = insert(node.left, key)40    else:41        node.right = insert(node.right, key)42    update(node)43    balance = height(node.left) - height(node.right)44    # Four imbalance cases: LL, RR, LR, RL45    if balance > 1 and key < node.left.key:46        return rotate_right(node)47    if balance < -1 and key > node.right.key:48        return rotate_left(node)49    if balance > 1:50        node.left = rotate_left(node.left)51        return rotate_right(node)52    if balance < -1:53        node.right = rotate_right(node.right)54        return rotate_left(node)55    return node56
57
58def inorder(node):59    if node is None:60        return []61    return inorder(node.left) + [node.key] + inorder(node.right)62
63
64root = None65for key in [10, 20, 30, 40, 50, 25]:66    root = insert(root, key)67
68print("Inorder:", inorder(root))69print("Root:", root.key, "| tree height:", root.height)
Führe diesen Code im Python-Playground aus

AVL-Baum-FAQ

Was ist ein Balancefaktor in einem AVL-Baum?
Der Balancefaktor eines Knotens ist die Höhe seines linken Teilbaums minus die Höhe seines rechten Teilbaums. Ein AVL-Baum hält den Balancefaktor jedes Knotens bei -1, 0 oder +1; wenn eine Einfügung ihn aus diesem Bereich schiebt, stellt eine Rotation das Gleichgewicht wieder her.
Was ist der Unterschied zwischen einem AVL-Baum und einem Rot-Schwarz-Baum?
Beide sind selbstausgleichende BSTs mit O(log n)-Operationen. AVL-Bäume sind strenger ausgeglichen, sodass Suchvorgänge etwas schneller sind, aber sie führen beim Einfügen/Löschen möglicherweise mehr Rotationen durch. Rot-Schwarz-Bäume sind lockerer ausgeglichen und bevorzugen weniger Rotationen - deshalb verwenden viele Standardbibliotheken sie für Maps und Sets.
Warum einen AVL-Baum statt eines einfachen binären Suchbaums verwenden?
Ein einfacher BST kann zu O(n)-Operationen degenerieren, wenn Werte in sortierter Reihenfolge eintreffen und eine schiefe Kette bilden. Ein AVL-Baum rotiert, um ausgeglichen zu bleiben, und garantiert eine Höhe und Operationen von O(log n) unabhängig von der Einfügereihenfolge.
Ist ein AVL-Baum besser als ein Rot-Schwarz-Baum für einen Datenbankindex?
Es hängt von der Arbeitslast ab. AVL-Bäume sind starrer ausgeglichen und gewinnen daher, wenn Lesevorgänge dominieren und Sie die kürzestmöglichen Suchpfade wollen. Aber die meisten Datenbanken und Sprachbibliotheken wählen Rot-Schwarz-Bäume (oder B-Bäume), weil sie sich bei schreiblastigen Arbeitslasten mit weniger Rotationen rebalancieren, was wichtiger ist, wenn Einfügungen und Löschungen häufig sind.
Wie viele Rotationen benötigt eine einzelne AVL-Einfügung?
Höchstens eine Rotation - entweder eine einfache oder eine doppelte (zweistufige) Rotation - wird jemals benötigt, um den Baum nach dem Einfügen eines Wertes neu auszugleichen. Das liegt daran, dass eine Einfügung die Höhe eines Teilbaums um höchstens eins erhöht, sodass eine einzige Korrektur am untersten unausgeglichenen Vorfahren ausreicht. Das Löschen ist anders: Es kann bis zu O(log n) Rotationen erfordern, wenn sich das Rebalancieren zur Wurzel hin ausbreitet.
Muss ich die Knotenhöhen nach jeder Rotation aktualisieren?
Ja - ein häufiger Fehler besteht darin, die Zeiger korrekt zu rotieren, aber zu vergessen, die Höhe der beiden beteiligten Knoten neu zu berechnen. Nach jeder Rotation müssen Sie zuerst die Höhe des herabgestuften Knotens und dann die des beförderten Knotens aktualisieren, da die Höhe des beförderten Knotens von seinen neuen Kindern abhängt. Wird dies ausgelassen, bleiben veraltete Balancefaktoren zurück, die künftige Rebalancierungsentscheidungen zerstören.
Coddy programming languages illustration

Meistere Algorithmen mit Coddy

LOS GEHT'S