Strona główna Algorytmy i Struktury Danych Drzewo czerwono-czarne — samoważące się BST

🌲 Drzewo czerwono-czarne — samoważące się BST

Wstawiaj i usuwaj klucze w drzewie czerwono-czarnym i patrz, jak przekolorowania i rotacje utrzymują równowagę. Każda ścieżka ma tę samą czarną wysokość, więc wyszukiwanie, wstawianie i usuwanie pozostają O(log n).

Algorytmy i Struktury Danych2DZaawansowany60 FPS
red-black-tree ↗ Otwórz osobno
Interfejs samej symulacji jest w języku angielskim.

O drzewie czerwono-czarnym

Drzewo czerwono-czarne to samobalansujące się binarne drzewo poszukiwań wprowadzone przez Rudolfa Bayera (1972), a później nazwane przez Leonidasa Guibasa i Roberta Sedgewicka (1978). Utrzymuje ono cztery niezmienniki koloru: korzeń jest czarny; żaden czerwony węzeł nie ma czerwonego rodzica; każda ścieżka od dowolnego węzła do pustego liścia zawiera tę samą liczbę czarnych węzłów (czarną wysokość); a puste liście są traktowane jako czarne. Zasady te zapewniają, że wysokość drzewa nigdy nie przekracza 2·log2(n+1), gwarantując czas O(log n) w najgorszym przypadku dla wyszukiwania, wstawiania i usuwania. Drzewa czerwono-czarne stanowią podstawę standardowych kontenerów map/zbiorów w C++ (std::map), Javie (TreeMap) oraz w kompletnie sprawiedliwym planiście Linuksa (CFS).

Ta symulacja pozwala wstawiać lub usuwać klucze pojedynczo, obserwując każdy krok przekolorowania i rotacji lewo/prawo animowany w czasie rzeczywistym. Licznik wysokości porównuje bieżącą wysokość drzewa czerwono-czarnego z równoważnym niezbalansowanym BST, by pokazać praktyczną korzyść z niezmienników.

Najczęściej zadawane pytania

Jakie są cztery niezmienniki drzewa czerwono-czarnego?

1) Każdy węzeł jest czerwony albo czarny. 2) Korzeń jest czarny. 3) Każdy pusty (liść) jest czarny. 4) Jeśli węzeł jest czerwony, oba jego dzieci są czarne (żadne dwa kolejne czerwone węzły na żadnej ścieżce). Dodatkowo 5) wszystkie ścieżki od dowolnego węzła do jego potomnych pustych liści przechodzą przez tę samą liczbę czarnych węzłów — to własność czarnej wysokości, która zapewnia balans.

Ile rotacji może wymagać pojedyncze wstawienie?

Co najwyżej dwie rotacje na wstawienie, plus O(log n) operacji przekolorowania propagujących się w górę. Dla porównania, drzewo AVL może wymagać O(log n) rotacji po wstawieniu (choć w praktyce średnio mniej). Dla usuwania drzewo czerwono-czarne może potrzebować co najwyżej trzech rotacji. Ta ograniczona liczba rotacji czyni drzewa czerwono-czarne atrakcyjnymi w systemach, gdzie rotacje są kosztowne, takich jak trwałe lub funkcyjne struktury danych.

Jak drzewo czerwono-czarne wypada w porównaniu z drzewem AVL?

Drzewa AVL utrzymują ściślejszy balans wysokości (różnica wysokości między poddrzewami ≤ 1), dając nieco szybsze wyszukiwania średnio. Drzewa czerwono-czarne dopuszczają stosunek wysokości do 2:1 między najdłuższą a najkrótszą ścieżką, co pozwala na szybsze wstawianie i usuwanie dzięki mniejszej liczbie rotacji. W obciążeniach z dużą liczbą zapisów (bazy danych, planiści systemu operacyjnego) zwykle preferowane są drzewa czerwono-czarne; w tabelach wyszukiwania z dużą liczbą odczytów drzewa AVL mogą być szybsze.

Czym jest rotacja w lewo i kiedy jest stosowana?

Rotacja w lewo wokół węzła x sprawia, że prawe dziecko x, y, staje się nowym korzeniem poddrzewa, przesuwając x w dół jako lewe dziecko y i przyjmując dawne lewe poddrzewo y jako nowe prawe dziecko x. Jest stosowana, gdy drzewo ma niezbalansowanie skierowane w prawo — konkretnie podczas wstawiania, gdy nowy czerwony węzeł jest prawym dzieckiem prawego dziecka (przypadek „prawo-prawo” w naprawie po wstawieniu).

Dlaczego własność czarnej wysokości gwarantuje wysokość O(log n)?

Niech bh(x) będzie czarną wysokością węzła x. Zgodnie z zasadą braku kolejnych czerwonych, co najwyżej połowa węzłów na dowolnej ścieżce od korzenia do liścia może być czerwona, więc rzeczywista wysokość h ≤ 2·bh(korzeń). Poddrzewo zakorzenione w dowolnym węźle o czarnej wysokości k zawiera co najmniej 2k−1 węzłów wewnętrznych, więc n ≥ 2bh−1, dając bh ≤ log2(n+1) i h ≤ 2·log2(n+1).

Jak drzewa czerwono-czarne są wykorzystywane w jądrze Linuksa?

Kompletnie sprawiedliwy planista Linuksa (CFS) przechowuje uruchamialne procesy w drzewie czerwono-czarnym kluczowanym wirtualnym czasem działania, dzięki czemu proces o najmniejszym czasie działania (następny do uruchomienia) można znaleźć w czasie O(log n). Menedżer pamięci jądra używa drzew czerwono-czarnych do śledzenia obszarów pamięci wirtualnej (VMA) na proces, a podsystem epoll używa ich do efektywnego zarządzania deskryptorami plików.

Czym jest drzewo 2-3-4 i jak wiąże się z drzewem czerwono-czarnym?

Drzewo 2-3-4 (lub B-drzewo rzędu 4) przechowuje 1–3 klucze na węzeł z 2–4 dziećmi, utrzymując idealny balans. Każde drzewo 2-3-4 mapuje się dokładnie na drzewo czerwono-czarne: węzeł 2 staje się pojedynczym czarnym węzłem; węzeł 3 staje się czarnym węzłem z czerwonym dzieckiem; węzeł 4 staje się czarnym węzłem z dwojgiem czerwonych dzieci. Ta odpowiedniość daje alternatywny dowód poprawności drzewa czerwono-czarnego i stanowi podstawę wariantu drzewa LLRB (lewoskrętnego czerwono-czarnego).

Czym jest lewoskrętne drzewo czerwono-czarne (LLRB)?

Wariant LLRB, spopularyzowany przez Roberta Sedgewicka (2008), dodaje ograniczenie, że czerwone łącza zawsze skręcają w lewo (czerwony węzeł jest zawsze lewym dzieckiem). Redukuje to liczbę przypadków strukturalnych do obsłużenia podczas wstawiania i usuwania z około 6–8 do 3, dając implementacje o mniej więcej 50 liniach kodu w porównaniu z ponad 200 dla standardowego sformułowania Cormena-Leisersona-Rivesta. TreeMap w Javie używa standardowego sformułowania; niektóre biblioteki języków funkcyjnych preferują LLRB.

Czy drzewa czerwono-czarne mogą być trwałe (persistent)?

Tak. Ponieważ każde wstawienie lub usunięcie modyfikuje tylko O(log n) węzłów (wzdłuż ścieżki od korzenia do dotkniętego liścia), trwałe drzewo czerwono-czarne można stworzyć przez kopiowanie ścieżki: duplikowanie jedynie O(log n) węzłów, które się zmieniają, i współdzielenie reszty. Daje to czas i pamięć O(log n) na operację z pełną historią wersji i jest wykorzystywane w trwałych funkcyjnych strukturach danych, takich jak posortowane mapy w Clojure.

Jak działa usuwanie w drzewie czerwono-czarnym?

Usuwanie najpierw wykonuje standardowe usuwanie BST (zastępując węzeł jego następnikiem in-order, jeśli ma dwoje dzieci). Jeśli usunięty węzeł lub jego zastępca był czerwony, nie dochodzi do naruszenia czarnej wysokości. Jeśli usunięty zostanie czarny węzeł, deficyt „podwójnej czerni” propaguje się w górę i jest rozwiązywany przez sześć przypadków analizy koloru rodzeństwa i bratanków, z których każdy albo przekorzeniuje poddrzewo za pomocą rotacji i przekolorowania, albo przesuwa deficyt w górę. Wystarczą co najwyżej trzy rotacje.

Podobne symulacje