Drzewa zbalansowane AVL i 2-3-4
Transkrypt
Drzewa zbalansowane AVL i 2-3-4
Wykład 2 Drzewa zbalansowane AVL i 2-3-4 1 Drzewa AVL Wprowadzenie Drzewa AVL – Definicja drzewa AVL – Operacje wstawiania i usuwania – Złożoność obliczeniowa Drzewa 2-3-4 – Definicja drzewa 2-3-4 – Operacje wstawiania i usuwania – Złożoność obliczeniowa Literatura – R. Sedgewick, “Algorytmy w C++”, rozdz. 13 2 Wprowadzenie Drzewa BST są wygodne do efektywnego implementowania operacji: Search, Successor, Predecessor, Minimum, Maximum, Insert, Delete w czasie O(h), (gdzie h jest wysokością drzewa) Jeśli drzewo jest zbalansowane (ma wtedy wysokość h = O(lg n)), operacje te są najbardziej efektywne. Operacje wstawiania i usuwania elementów mogą powodować, że drzewo przestaje być zbalansowane. W najgorszym przypadku drzewo staje się listą liniową (h = O(n))! 3 Drzewa zbalansowane Staramy się znaleźć takie metody operowania na drzewie, żeby pozostawało ono zbalansowane. Jeżeli operacja Insert lub Delete spowoduje utratę zbalansowania drzewa, będziemy przywracać tę własność w czasie co najwyżej O(lgn) tak aby nie zwiększać złożoności. Potrzebujemy zapamiętywać dodatkowe informacje, aby to osiągnąć. Najbardziej popularne struktury danych dla drzew zbalansowanych to: – Drzewa AVL: różnica wysokości dla poddrzew wynosi co najwyżej 1 – Drzewa 2-3-4 drzewa zbalansowane, ale nie binarne – Drzewa czerwono-czarne: o wysokości co najwyżej 2(lg n + 1) 4 Drzewa AVL Definicja: drzewem AVL nazywamy drzewo BST, takie że dla każdego z węzłów różnica wysokości jego lewego i prawego poddrzewa wynosi co najwyżej 1. Skrót AVL pochodzi od nazwisk twórców: Adelson-Velskii oraz Landis x h h-1 S h-1 Sh-2 h-2 Sh Sh = Sh–1 + Sh–2 5 Przykład drzewa AVL 4 44 2 3 17 78 1 2 32 1 88 50 1 48 62 1 6 Wysokość drzewa AVL Twierdzenie:wysokość drzewa AVL przechowującego n węzłów wynosi O(log n). n(2) 3 4 n(1) Dowód: ograniczymy najpierw n(h): minimalną ilość wewnętrznych węzłów w drzewie AVL o wysokości h. – widać, że n(1) = 1 i n(2) = 2 – dla n > 2, drzewo o wysokości h zawiera korzeń oraz dwa poddrzewa o wysokościach h-1 i h-2. stąd: n(h) = 1 + n(h-1) + n(h-2) – wiemy, że n(h-1) > n(h-2), więc n(h) > 2n(h-2). Dalej n(h) > 2n(h-2), n(h) > 4n(h-4), n(h) > 8n(n-6), …,n(h) > 2in(h-2i) – rozwiązując powyższe dostaniemy n(h) > 2 h/2-1 , czyli h < 2log n(h) +2 Stąd wysokość drzewa AVL wynosi O(log n) 7 Wstawianie Wstawiamy tak jak do drzewa BST Zawsze dodajemy nowy liść. Przykład : 44 44 17 78 17 78 c=z a=y 32 50 48 88 62 32 50 88 48 62 b=x 54 w przed po wstawieniu 54 8 Przebudowa drzewa niech (a,b,c) będzie pożądaną listą wierzchołków w porządku inorder Przeprowadzamy rotacje, niezbędne do przemieszczenia b na górę poddrzewa (pozostałe dwa przypadki są symetryczne) a=z a=z przypadek 2: podwójna rotacja (prawa c, a potem lewa a) c=y b=y T0 T0 b=x c=x T3 T1 b=y T2 b=x T1 T3 a=z przypadek 1: pojedyncza Rotacja (lewa rotacja a) T0 T2 c=x T1 T2 a=z T3 T0 c=y T1 T2 T3 9 Rotacje (przypomnienie) Rotacja w prawo y x Rotacja w lewo x α δ β α≤x≤β i x≤y≤δ y α β δ α≤x≤y i β≤y≤δ 10 Przykład: Left-Rotate (1) 7 4 3 x 11 6 9 19 14 2 12 y 18 22 17 20 11 Przykład: Left-Rotate (2) 7 4 3 x 11 6 9 α 2 y 18 19 14 12 22 17 β 20 δ 12 Przykład: Left-Rotate (3) 7 4 3 2 y 18 x 11 6 19 14 9 22 α 12 17 β 20 δ 13 Przykład (wstawiamy element 54) 4 44 2 3 17 78 1 2 32 1 88 50 1 48 62 1 5 44 z 2 17 3 1 1 32 78 2y 2 1 1 7 1 50 48 64 3 4 62 x 88 5 T3 54 T2 T0 T1 14 Przykład (po wstawieniu 54) 5 44 z 2 17 3 1 32 1 1 50 2 1 1 7 78 2 y 48 64 3 4 62 88 x 5 T3 54 niezbalansowane... T2 T0 T1 44 4 3 2 17 32 1 1 48 50 x z6 62 2 y 2 1 4 3 1 5 78 54 ...zbalansowane 2 7 1 88 T2 T0 T1 T3 15 Przebudowa drzewa (pojedyncza rotacja – przyp. 1) 1 rotacja a=z b=y b=y a=z c=x c=x T0 T3 T1 T3 T0 T1 T2 T2 1 rotacja c=z b=y b=y a=x c=z a=x T3 T0 T2 T3 T2 T1 T0 T1 16 Przebudowa drzewa (podwójna rotacja – przyp. 2) 2 rotacje a=z b=x c=y a=z c=y b=x T0 T3 T2 T0 T2 T1 T3 T1 2 rotacje c=z b=x a=y a=y c=z b=x T3 T0 T2 T3 T2 T1 T0 T1 17 Usuwanie z drzewa AVL Usuwamy, jak z drzewa BST – może spowodować to zaburzenie zbalansowania drzewa. Przykład: 44 44 17 62 32 50 48 17 62 78 54 Przed usunięciem 32 50 88 48 78 54 88 Po usunięciu 18 Przywracanie zbalansowania po usunięciu Niech z będzie pierwszym „niezbalansowanym” węzłem, na który natrafiamy idąc od w. Niech y będzie dzieckiem z o większej wysokości, a x jego dzieckiem o większej wysokości. Przeprowadzamy przebudowę drzewa w x , tak aby przywrócić zbalansowanie w z (węzły a,b,c mają być w porządku inorder). Ponieważ operacja taka może zachwiać balans w węźle powyżej musimy sprawdzać zbalansowanie drzewa powyżej (aż do korzenia) a=z w 62 44 17 50 48 c=x 78 54 44 b=y 62 88 17 78 50 48 88 54 19 Złożoność obliczeniowa operacji na drzewach AVL Pojedyncza przebudowa zabiera czas O(1) – Jeśli korzystamy ze struktury drzewa binarnego (tylko 1 lub 2 rotacje) Wyszukiwanie zajmuje O(log n) – Wysokość drzewa wynosi O(log n), nie potrzeba przebudowywać drzewa Wstawianie zajmuje O(log n) – Odnalezienie miejsca O(log n) – Przebudowa drzewa O(log n) – ze względu na wysokość drzewa Usuwanie - O(log n) – Odnalezienie zabiera czas O(log n) – Naprawa drzewa O(log n) – ze względu na wysokość drzewa 20 Drzewa 2-3-4 9 2 5 7 10 14 21 Drzewa poszukiwań o wielu drogach Drzewem poszukiwań o wielu drogach (B-drzewem) nazywamy uporządkowane drzewo o następujących cechach: – Każdy węzeł wewnętrzny posiada co najmniej 2 potomków i przechowuje d −1 elementów-kluczy (ki, oi), gdzie d jest ilością potomków węzła – Dla każdego węzła o potomkach v1 v2 … vd przechowującego klucze k1 k2 … kd−1 • Klucze w poddrzewie v1 są mniejsze od k1 • Klucze w poddrzewie vi są pomiędzy ki−1 i ki (i = 2, …, d − 1) • Klucze w poddrzewie vd są większe od kd−1 – Liście nie przechowują kluczy 11 2 6 8 24 15 27 32 30 22 Przechodzenie InOrder w drzewach o wielu drogach Możliwe jest rozszerzenie notacji odwiedzania węzłów InOrder z drzew binarnych na drzewa o wielu drogach Odwiedzamy element (ki, oi) w węźle v pomiędzy rekursywnymi odwiedzinami poddrzew v o korzeniu w vi i vi + 1 Odwiedzane węzły w tak zdefiniowanym porządku InOrder są uporządkowane rosnąco 11 24 8 2 6 8 2 4 12 15 6 27 32 14 10 18 30 1 3 5 7 9 11 13 19 16 15 17 23 Poszukiwanie w drzewach o wielu drogach Podobnie do poszukiwania w drzewie BST Dla każdego węzła wewnętrznego o potomkach v1 v2 … vd o kluczach k1 k2 … kd−−1: – k = ki (i = 1, …, d − 1):poszukiwanie zakończone sukcesem – k < k1: poszukiwanie kontynuujemy w poddrzewie v1 – ki−1 < k < ki (i = 2, …, d − 1): poszukiwanie kontynuujemy w poddrzewie vi – k > kd−1: poszukiwania kontynuujemy w poddrzewie vd Dotarcie do liścia kończy poszukiwania (porażka) Przykład : odszukujemy klucza 30 11 2 6 8 24 15 27 32 30 24 Drzewa 2-3-4 Drzewa 2-3-4 – nazywane też (2,4) – są drzewami poszukiwań o wielu drogach o następujących własnościach – własność ilości potomków: każdy węzeł wewnętrzny ma co najwyżej 4 potomków – własność wysokości: wszystkie liście mają tę samą wysokość W zależności od ilości potomków, wewnętrzne węzły będziemy nazywać 2-węzłami, 3-węzłami i 4-węzłami 10 15 24 2 8 12 18 27 32 25 Wysokość w drzewach 2-3-4 Twierdzenie: Drzewo 2-3-4 przechowujące n elementów ma wysokość O(log n) dowód: – niech h będzie wysokością drzewa 2-3-4 o n elementach – ponieważ mamy co najmniej 2i elementów na poziomie i = 0, … , h − 1 i nie ma elementów ma poziomie h, więc n ≥ 1 + 2 + 4 + … + 2h−1 = 2h − 1 – stąd, h ≤ log (n + 1) Wyszukiwanie w drzewie 2-3-4 o n elementach zajmuje czas O(log n) poziom elementy 0 1 1 2 h−1 2h−1 h 0 26 Wstawianie Nowy element (k, o) wstawiamy do węzła v – ostatniego wewnętrznego węzła, przez który przechodziliśmy poszukując k – Nie psujemy własności wysokości drzewa – Możemy spowodować przepełnienie węzła (v może stać się 5-węzłem) Przykład: wstawianie 30 powoduje przepełnienie 10 15 24 2 8 12 18 10 15 24 2 8 12 18 v 27 32 35 v 27 30 32 35 27 Przepełnienie i rozdzielanie węzła Problem przepełnienia można rozwiązać przez podział węzła v: – niech v1 … v5 będą potomkami v i k1 … k4 będą kluczami w v – węzeł v zastępujemy 2 węzłami v' i v" • v' jest 3-węzłem o kluczach k1 k2 i potomkach v1 v2 v3 • v" jest 2-węzłem o kluczach k4 i potomkach v4 v5 – klucz k3 jest wstawiany do rodzica u węzła v (to może tworzyć nowy korzeń) Przepełnienie może teraz nastąpić w węźle u u u 15 24 32 15 24 v 12 18 27 30 32 35 v1 v2 v3 v4 v5 v' 12 18 27 30 v1 v2 v3 v4 v" 35 v5 28 Analiza wstawiania Algorytm insertItem(k, o) 1. Odszukujemy klucz k w celu zlokalizowania węzła do wstawienia wartości v 2. Dodajemy nowy element (k, o) w węźle v 3. while overflow(v) if isRoot(v) twórz nowy pusty korzeń nad v v ← split(v) Niech T będzie drzewem 2-3-4 o n elementach – T ma wysokość O(log n) – krok 1 zajmuje czas O(log n), ponieważ odwiedzamy O(log n) węzłów – krok 2 zajmuje czas O(1) – krok 3 zabiera O(log n) czasu, ponieważ każde rozdzielanie zabiera O(1) i możemy mieć O(log n) takich operacji Stąd wstawianie do drzewa 2-3-4 zajmuje czas O(log n) 29 Usuwanie Rozważania na temat usuwania można sprowadzić tylko do przypadku usuwania wartości z węzła posiadającego jedynie potomków liście W przeciwnym razie (węzły wewnętrzne) zastępujemy element kolejnym w porządku inorder (następnikiem – jego lewe dziecko musi być liściem) Przykład: usuwanie 24 – zastępujemy 24 przez następnik w porządku inorder - 27 10 15 24 2 8 12 18 27 32 35 10 15 27 2 8 12 18 32 35 30 Niedobór i łączenie Usunięcie elementu z węzła v może spowodować niedobór - v może stać się 1-węzłem (0 klucz, 1 potomek) Dla obsługi tej sytuacji należy połączyć v z rodzicem u, rozpatrzmy dwa przypadki przypadek 1: sąsiedni brat v jest 2-węzłem – operacja łączenia: łączymy v z bratem w i przenosimy element z u do połączonego węzła v' – po połączeniu, niedobór może nastąpić w węźle powyżej (u) u u 9 14 w 2 5 7 10 9 v' v 2 5 7 10 14 31 Niedobór i łączenie przypadek 2: sąsiedni brat w węzła v jest 3-węzłem lub 4-węzłem – przenosimy: 1. potomka w do v 2. element z u do v 3. element z w do u – po przeniesieniu nie występują przepełnienia u u 4 9 4 8 w 2 6 8 v w 2 6 v 9 32 Analiza usuwania Niech T będzie drzewem 2-3-4 o n elementach – wysokość T wynosi O(log n) Operacja usuwania: – odwiedzamy O(log n) węzłów aby odszukać węzeł, z którego usuwamy element – obsługa niedoborów może prowadzić do wykonania serii O(log n) łączeń węzłów (przyp. 1) oraz jednego przesuwania (przyp. 2) – każde łączenie zajmuje O(1) Stąd operacja usuwania w drzewie 2-3-4 zajmuje czas O(log n) 33