Drzewa binarne Każdy węzeł w drzewie posiada pola: klucz, adres prawego potomka i adres lewego potomka. Pola zawierające adresy mogą być puste. Uporządkowanie. Zakładamy, że klucze są różne. Klucze leżące w lewym poddrzewie danego węzła są mniejsze od klucza w danym węźle, a klucze leżące w prawym poddrzewie są większe. Poszukiwanie klucza jest łatwe. Wstawianie. Nowy klucz (wraz z nowym węzłem) wstawiamy na końcu ścieżki od korzenia od liścia. 8 8 7 Usuwanie. Klucz z liścia lub z węzła posiadającego jednego potomka usuwamy łatwo (podpinamy poddrzewo w miejsce usuwanego węzła). 7 7 6 8 6 8 Aby usunąć klucz z węzła posiadającego dwóch potomków, usuwany klucz zamieniamy na najmniejszy klucz w prawym poddrzewie. Teraz w drzewie mamy dwa równe klucze, z których niżej położony należy usunąć. Węzeł w którym leży klucz do usunięcia posiada co najwyżej jednego potomka.
8 8 0 0 6 9 6 9 7 7 Drzewa czerwono-czarne Liczba operacji przy poszukiwaniu, wstawianiu i usuwaniu jest ograniczona wysokością drzewa. Dlatego zależy nam, aby drzewa były zrównoważone (nie miały równocześnie długich i krótkich ścieżek od korzenia do liści). Jednym z pomysłów na szybkie równoważenie drzewa po operacjach wstawiania i usuwania są drzewa czerwono-czarne. Są to drzewa binarne z dodatkowym polem w każdym węźle oznaczającym kolor (czarny lub czerwony). Zakłada się, że. korzeń jest czarny. czerwony węzeł nie może mieć czerwonego potomka. węzły o adresie zero traktuje się jako czarne liście (potrzebne, aby prosto wyrazić następną własność). na każdej ścieżce od korzenia do liścia leży tyle samo czarnych węzłów Wynika stąd, że najdłuższa ścieżka jest najwyżej dwa razy dłuższa od najkrótszej.
0 0 6 6 8 8 7 9 7 9 Wstawianie i usuwanie zaczynamy jak w przypadku drzewa binarnego. Następnie w razie potrzeby naprawiamy drzewo przemalowując węzły lub wykonując jedną lub dwie rotacje (przekształcenie pokazane na rysunku). Wstawianie. Nowy klucz wstawiamy, jak do zwykłego drzewa binarnego. Nowy węzeł malujemy na czerwono. Jeśli nowy węzeł jest potomkiem czarnego węzła kończymy. W przeciwnym wypadku naprawiamy drzewo (naruszona własność druga, wyjątkowo pierwsza gdy drzewo jest puste). Rozpatrujemy trzy przypadki. Pierwszy przypadek może się powtarzać, kończyć naprawę (być może po przemalowaniu korzenia na czarno) lub prowadzić do drugiego czy też trzeciego przypadku. Drugi przypadek prowadzi do trzeciego, a trzeci od razu kończy naprawę.. Jeśli ojciec i wujek są czerwoni, przemalowujemy ojca i wujka na czarno, a dziadka na czerwono i pytamy, czy przemalowany na czerwono dziadek nie ma czerwonego ojca. W ten sposób przenosimy się dwa poziomy wyżej (wykrzyknik oznacza węzeł sprawiający problem, na początku jest to nowowstawiony węzeł).
. Jeśli ojciec jest czerwony, a wujek czarny (lub brak wujka) i linia łącząca z dziadkiem załamuje się, wykonujemy rotację i przechodzimy do trzeciego przypadku.. Jeśli ojciec jest czerwony, a wujek czarny i linia łącząca z dziadkiem jest prosta, wykonujemy rotację i kończymy. Usuwanie. Węzeł usuwamy tak, jak ze zwykłego drzewa binarnego. Jeśli faktycznie usuwany węzeł jest czerwony, kończymy. W przeciwnym wypadku naprawiamy drzewo (naruszona własność czwarta, wyjątkowo pierwsza). Naprawę zaczynamy od węzła który znalazł się w miejscu faktycznie usuniętego węzła. Jeśli jest to czerwony węzeł, wystarczy przemalować go na czarno. W przeciwnym wypadku rozpatrujemy przypadki. Pierwszy przypadek po rotacji zamienia się na drugi, trzeci lub czwarty przypadek. W drugim przypadku przemalowanie kończy naprawę lub przenosi problem poziom wyżej. Trzeci przypadek po rotacji zamienia się na przypadek czwarty, a czwarty przypadek po rotacji kończy naprawę drzewa.. Jeśli brat jest czerwony, wykonując rotację, otrzymujemy przypadek drugi, trzeci bądź czwarty.
. Jeśli brat jest czarny i czarni są bratankowie, przemalowując węzły, przenosimy problem na ojca. Jeśli ojciec jest czerwony, przemalowujemy go na czarno i kończymy naprawę.. Jeśli brat jest czarny, a bliższy bratanek czerwony, wykonujemy rotację i przechodzimy do czwartego przypadku.. Jeśli brat jest czarny, a dalszy bratanek czerwony, wykonujemy rotację i kończymy naprawę. Uwaga. Kolory żółty i zielony na lewym i prawym rysunku oznaczają ten sam kolor (czerwony lub czarny).
B-drzewa B-drzewa są jeszcze jednym przykładem struktury wskaźnikowej.. Każdy węzeł B-drzewa posiada t miejsc na przechowywanie kluczy, t miejsc na adresy dzieci oraz zmienną mówiącą, ile faktycznie kluczy występuje w danym węźle. Parametr t jest ustaloną liczbą.. Liście nie przechowują adresów. Węzeł będący liściem nigdy nie zamienia się na węzeł wewnętrzny.. Korzeń może zawierać od jednego klucza do t kluczy. Pozostałe węzły zawierają od t kluczy do t kluczy. Liczba adresów przechowywanych w węźle jest o jeden większa od liczby kluczy w węźle.. Możemy myśleć, że adresy w danym węźle porozdzielane są kluczami. Uporządkowanie kluczy jest takie samo, jak uporządkowanie kluczy w drzewie binarnym. Klucze w węźle uporządkowane są rosnąco. Poddrzewa zawierają klucze o pośrednich wartościach.. Wszystkie liście leżą na tym samym poziomie (wzrost i zmniejszanie wysokości drzewa odbywa się przy korzeniu). 6. Poszukiwanie klucza jest oczywiste. 7. Wstawianie wymaga czasem operacji rozbijania węzła, natomiast usuwanie wymaga czasem pożyczenia klucza od brata lub sklejenia dwóch węzłów. 8. Rozbijanie pełnego węzła (możliwe, jeśli ojciec nie jest pełny). 6
9. Aby rozbić pełny korzeń, tworzymy nowy korzeń. Jest to jedyny moment, w którym rośnie wysokość drzewa. 0. Klucze wstawimy w liściach (w przypadku pustego drzewa, tworzymy korzeń będący jednocześnie liściem). Aby wstawić klucz, schodzimy od korzenia do liścia. Na wszelki wypadek wszystkie pełne węzły napotkane po drodze rozbijamy. Dzięki temu na pewno będziemy mogli rozbić pełny liść i znaleźć miejsce na nowy klucz. Opisany algorytm wymaga tylko jednego przejścia od korzenia do liścia.. Pożyczanie od brata.. Jeśli musimy powiększyć węzeł, a nie możemy pożyczyć od żadnego z braci, sklejamy węzeł z bratem (operacja odwrotna do rozbijania). Sklejenie jest możliwe, o ile ojciec nie nie zawiera minimalnej liczby kluczy. Jeśli chcemy skleić dzieci korzenia zawierającego jeden klucz, z korzenia i dwóch jego dzieci tworzymy nowy korzeń. Jest to jedyny moment, w którym maleje wysokość drzewa, poza oczywistym przypadkiem usuwania jedynego klucza z drzewa. 7
. Usuwanie węzła wewnętrznego poprzedzone jest skopiowaniem w miejsce usuwanego klucza największego klucza z lewego poddrzewa (lub najmniejszego klucza z prawego poddrzewa). Największy klucz w lewym poddrzewie leży w liściu i należy go usunąć.. Aby usunąć węzeł z liścia, schodzimy od korzenia do liścia, dbając, aby żaden węzeł po drodze nie był minimalny. Napotkane minimalne węzły powiększamy pożyczając lub jeśli to niemożliwe, sklejając węzły. Dzięki temu na pewno będziemy mogli powiększyć w razie potrzeby liść, z którego usuwamy klucz. Opisany algorytm wymaga tylko jednego przejścia od korzenia do liścia. Chciałbym podziękować Pani Joannie za wykonanie ładnych rysunków. 8