Menu
Coddy logo textTech

Drzewo AVL

Ostatnia aktualizacja

Drzewo AVL to samorównoważące się binarne drzewo poszukiwań. Działa jak zwykłe drzewo BST, ale po każdym wstawieniu sprawdza współczynnik zrównoważenia każdego przodka, czyli różnicę wysokości między jego lewym i prawym poddrzewem. Jeśli któryś węzeł traci równowagę (różnica większa niż 1), drzewo wykonuje rotacje, aby ją przywrócić. Kliknij odtwarzanie powyżej i zobacz, jak wstawiane są wartości, a drzewo samo wraca do właściwego kształtu.

Ponieważ drzewo AVL nigdy nie pozwala na więcej niż niewielkie przechylenie, gwarantuje wysokość O(log n), więc wyszukiwanie, wstawianie i usuwanie zawsze działają w O(log n), nawet dla posortowanych danych, które zrujnowałyby zwykłe drzewo BST. Kosztem są dodatkowe rotacje i aktualizacja wysokości przy każdym wstawieniu.

Złożoność czasowa i pamięciowa

OperacjaZłożonośćUwagi
WyszukiwanieO(log n)Wysokość zawsze wynosi ok. 1,44 log n
WstawianieO(log n)Plus O(1) rotacji
UsuwanieO(log n)Plus O(log n) rotacji
PamięćO(n)Jedno pole wysokości na węzeł

Cztery przypadki rotacji

PrzypadekNierównowagaNaprawa
Lewo-LewoPrzeciążone lewe poddrzewo lewego dzieckaJedna rotacja w prawo
Prawo-PrawoPrzeciążone prawe poddrzewo prawego dzieckaJedna rotacja w lewo
Lewo-PrawoPrzeciążone prawe poddrzewo lewego dzieckaRotacja w lewo, potem w prawo
Prawo-LewoPrzeciążone lewe poddrzewo prawego dzieckaRotacja w prawo, potem w lewo

Przykład krok po kroku

Wstawianie [10, 20, 30, 40, 50, 25] po jednej wartości:

KrokStrukturaDziałanie
Wstaw 1010Pierwszy węzeł zostaje korzeniem; drzewo jest zrównoważone
Wstaw 2010(_, 20)Trafia na prawo od 10; nadal równowaga
Wstaw 3020(10, 30)Prawo-Prawo w 10, więc jedna rotacja w lewo wynosi 20 na korzeń
Wstaw 4020(10, 30(_, 40))Trafia na prawo od 30; każdy współczynnik zrównoważenia mieści się w ±1
Wstaw 5020(10, 40(30, 50))Prawo-Prawo w 30, więc rotacja w lewo w 30 wynosi 40 wyżej
Wstaw 2530(20(10, 25), 40(_, 50))Prawo-Lewo w 20: rotacja w prawo poddrzewa 40, potem rotacja w lewo w 20

Kiedy używać drzewa AVL

Używaj, gdyUnikaj, gdy
Wyszukiwań jest znacznie więcej niż wstawień i zależy ci na najmniejszej możliwej wysokościDominują wstawienia i usunięcia: dodatkowe rotacje i równoważenie kosztują więcej niż w drzewie czerwono-czarnym
Potrzebujesz gwarantowanego O(log n) w najgorszym przypadku, nawet dla złośliwych lub posortowanych danychWystarczy zwykła tablica haszująca: nie potrzebujesz przechodzenia w porządku ani zapytań o zakres
Potrzebujesz operacji na uporządkowanych danych: przejścia in-order, poprzednika/następnika, zapytań o zakresZbiór danych jest malutki: zwykłe drzewo BST lub posortowana tablica są prostsze i wystarczająco szybkie
Dane mogą przychodzić już posortowane, co zamieniłoby niezrównoważone drzewo BST w listę jednokierunkowąNie możesz sobie pozwolić na dodatkową pamięć na pole wysokości w każdym węźle przy bardzo ciasnych zasobach

AVL Tree: kod

Przejrzysta, gotowa do uruchomienia implementacja algorytmu AVL Tree w językach: Python, JavaScript, Java, C++, C. Wybierz język, skopiuj kod albo otwórz go od razu w edytorze online Coddy.

AVL Tree: kod (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)
Uruchom ten kod w edytorze Python online

Drzewo AVL: najczęstsze pytania

Czym jest współczynnik zrównoważenia w drzewie AVL?
Współczynnik zrównoważenia węzła to wysokość jego lewego poddrzewa minus wysokość prawego poddrzewa. Drzewo AVL utrzymuje współczynnik każdego węzła na poziomie -1, 0 lub +1; jeśli wstawienie wypchnie go poza ten zakres, rotacja przywraca równowagę.
Czym różni się drzewo AVL od drzewa czerwono-czarnego?
Oba są samorównoważącymi się drzewami BST z operacjami w O(log n). Drzewa AVL są zrównoważone bardziej rygorystycznie, więc wyszukiwanie jest nieco szybsze, ale przy wstawianiu i usuwaniu mogą wykonywać więcej rotacji. Drzewa czerwono-czarne są zrównoważone luźniej i wymagają mniej rotacji, dlatego wiele bibliotek standardowych używa ich do map i zbiorów.
Po co używać drzewa AVL zamiast zwykłego binarnego drzewa poszukiwań?
Zwykłe drzewo BST może zdegradować się do operacji w O(n), jeśli wartości przychodzą w posortowanej kolejności i tworzą przekrzywiony łańcuch. Drzewo AVL wykonuje rotacje, aby pozostać zrównoważone, co gwarantuje wysokość i operacje w O(log n) niezależnie od kolejności wstawiania.
Czy drzewo AVL jest lepsze od drzewa czerwono-czarnego do indeksu w bazie danych?
To zależy od obciążenia. Drzewa AVL są zrównoważone sztywniej, więc wygrywają, gdy dominują odczyty i zależy ci na jak najkrótszych ścieżkach wyszukiwania. Większość baz danych i bibliotek językowych wybiera jednak drzewa czerwono-czarne (lub B-drzewa), bo przy intensywnych zapisach równoważą się mniejszą liczbą rotacji, co ma większe znaczenie przy częstych wstawieniach i usunięciach.
Ile rotacji wymaga jedno wstawienie do drzewa AVL?
Najwyżej jednej rotacji, pojedynczej albo podwójnej (dwuetapowej), aby przywrócić równowagę po wstawieniu jednej wartości. Wynika to z tego, że wstawienie zwiększa wysokość poddrzewa co najwyżej o jeden, więc wystarczy jedna naprawa w najniższym niezrównoważonym przodku. Usuwanie działa inaczej: może wymagać nawet O(log n) rotacji, bo równoważenie propaguje się w stronę korzenia.
Czy po każdej rotacji trzeba aktualizować wysokości węzłów?
Tak. Częsty błąd to poprawne przepięcie wskaźników bez ponownego obliczenia wysokości dwóch węzłów biorących udział w rotacji. Po każdej rotacji najpierw zaktualizuj wysokość węzła, który zszedł niżej, a potem węzła, który awansował, bo wysokość awansowanego węzła zależy od jego nowych dzieci. Pominięcie tego kroku zostawia nieaktualne współczynniki zrównoważenia, które psują kolejne decyzje o równoważeniu.
Ilustracja języków programowania w Coddy

Opanuj algorytmy z Coddy

ZACZNIJ