• Nie Znaleziono Wyników

Drzewa BST i AVL-drzewa

Zajęcia poświęcone są omówieniu struktur slownikowych na przykładzie drzew poszukowań binarnych BST oraz drzew wyważonych (drzew AVL). Przypo-mnijmy, że słownikiem jest struktura danych umożliwiająca wykonanie na-stępujacych operacji na skończonych zbiorach A ⊆ U , gdzir (U,6), zaś 6 jest liniowym porządkiem:

1. Construct (A) : A := ∅ 2. Insert (A, x) : A := A ∪ {x}

3. Delete(A, x) : A := A \ {x}

4. Access(A, x) : wyznacz adres elementu x w strukturze A (zwraca NULL, jeśli x 6∈ A)

5. Member (A, x) : funkcja logiczna o wartości true, jeśli x ∈ A i False w przeciwnym przypadku.

9.1 Drzewa poszukiwań binarnych

Drzewem poszukiwań binarnych (drzewem BST) nazywamy drzewo binarne takie, że dla każdego węzła v tego drzewa zachodzi warunek:

• jeśli węzeł w należy do lewego poddrzewa v, to w↑.key 6 v↑.key

• jeśli węzeł w należy do prawego poddrzewa v, to w↑.key > v↑.key.

Podstawowe operacje słownikowe

Przyponijmy teraz podstawowe operacje słownikowe. Algortm 9.1 ustala ad-res klucza x w drzewie t, a jeśli brak tego klucza w drzewie, zwraca NULL.

Dodatkowo algorytm ustala adres ojca węzła o kluczu x (parametr prev ), 53

o ile x występuje w drzewie i nie jest korzeniem, w przeciwnym przypadku wynikową wartością parametru prev jest NULL.

Algorytm 9.1: Wyszukanie adresu klucza w drzewie BST 1 Access(t : tree; var prev : tree; x : Data) : tree;

2 begin

3 prev :=NULL;

4 while t 6= NULL do

5 if t↑.key = x then return(t) fi;

6 prev := t;

7 if t↑.key < x then t := t↑.right else t := t↑.left fi

8 od;

9 return(NULL) 10 end Access;

Algorytm 9.2:Wstawienie elementu do drzewa BST 1 Insert (var t : tree, x : Data);

2 var v, prev : tree; cont : Bool;

3 begin

4 v :=Access(t, prev, x);

5 if v 6= NULL then exit fi;

6 new(v);

7 ↑.left := v↑.it right :=NULL; v↑.key := x;

8 if prev =NULL then t := v else

9 if prev ↑.key<x then prev ↑.right := v else prev ↑.right := v fi

10 fi

11 end Insert ;

W algorytmie 9.3 usuwania klucza z drzewa BST rozważane są w istocie 3 następujące przypadki:

(P1) klucz znajduje się w liściu – następuje “obcięcie” tego liścia

(P2) klucz znajduje się w węźle v, który ma tylko 1 następnik (lewy bądź prawy) – następuje przełączenie wskaźnika w ojcu tego węzła do tego następnika

(P3) klucz znajduje się w węźle v, który ma dokładnie 2 następniki – wyszu-kujemy maksymalny klucz w jego lewym poddrzewie (lub minimalny klucz w jego prawym poddrzewie), przenosimy ów klucz do węzła v, oraz usuwamy węzeł, z którego przenieśiśmy klucz

9.2. DRZEWA AVL 55 Algorytm AccessMax jest pomocny w przypadku (P3). Funkcja ta zwraca adres węzła o maksymalnym kluczu w drzewie v, a dodatkowo nadaje para-metrowi prev watość adresu ojca tego węzła.

Algorytm 9.3: Usuwanie elementu z drzewa BST 1 Delete(var t : tree, x : Data);

2 var v, prev : tree; cont : Bool;

3 begin

3 v :=Access(t, prev, x);

4 if v=NULL then exit fi;

5 if v↑.left=NULL

6 then do prev dowiąż prawy następnik v else 7 if v↑.left=NULL

8 then do prev dowiąż lewy następnik v else 9 w:=AccessMaxMin(v↑.left, prev);

10 v↑.key := w↑.key;

11 prev↑.right := w↑.left;

12 v := w;

13 fi

14 fi;

15 kill (v);

16 end Delete;

9.2 Drzewa AVL

Drzewem AVL (inaczej: drzewem wyważonym) nazywamy drzewo BST, w którym dla każdego węzła v spełniony jest warunek:

|height(t↑.right)−height(t↑.left)| 6 1.

Innymi slowy, albo oba poddrzewa są tej samej wysokości, albo jedno z nich jest wyższe od drugiego co najwyżej o 1.

Repezentację węzła drzewa AVL rozszerzamy o dodatkowy atrybut współ-czynnik wyważenia – jest to różnica wysokości jego prawego i lewego pod-drzewa (bądź odwrotnie, zależy od umowy).

Koszt modyfikacji drzewa (operacje wstawiania czy usuwania elementu) jest nieco większy niż dla zwykłego drzewa BST, ale za to własności drzewa AVL gwarantują, że pesymistyczny czas wyszukiwania elementu w drzewie o n węzłach wynosi Θ(lg n), podczas gdy dla niezrównoważonego BST (w postaci listy) czas ten wynosi Θ(n).

Operacje utworzenia drzewa AVL i wyszukania zadanego elementu w drzewie są identyczne jak dla zwykłych drzew BST. Modyfikacji ulegają operacje Insert i Delete, gdyż mogą one spowodować zaburzenie wyważe-nia drzewa.

Wstawianie elementu do drzewa AVL

Najpierw rekurencyjnie wstawiamy element tak jak do zwykłego drzewa BST, czyli dowiązujemy w odpowiednik miejscu nowy liść i w nim umieszcza-my element. Następnie wracaumieszcza-my po ścieżce w górę od dołączonego liścia co najwyżej do korzenia sprawdzając (ewentualnie modyfikując) współczynniki wyważenia i, jeśli zachodzi potrzeba, wyważając poddrzewa.

Schematy wyważania

Rysunek 9.1: Schemat LL Left-Left

Th+1

Rysunek 9.2: Schemat LR Left-Right

9.2. DRZEWA AVL 57

Rysunek 9.3: Schemat RR Right-Right

Th

Rysunek 9.4: Schemat RL Right-Left

Usuwanie elementu z drzewa AVL

Najpierw rekurencyjnie usuwany element tak jak ze zwykłego drzewa BST.

Poczynając od usuwanego węzła v proces “wraca” po ścieżce (maksymalnie) do korzenia w każdym węźle (jeśli potrzeba) modyfikując jego współczyn-nik wyważenia i ewentualnie dokonując wyważenia węzła poprzez wykonanie jednego z przedstawio omówionych schematów rotacji. Załóżmy, że algorytm wraca z lewego poddrzewa węzła v z parametrem decrease o wartości True (sygnał, że wysokość tego poddrzewa zmniejszyła się). Wówczas:

• Jeśli współczynnik wyważenia w węźle v wynosi 0, to zmniejszamy jego wartość i KONIEC, wpp przechodzimy do kolejnego punktu

• Jeśli współczynnik wyważenia w węźle v wynosi 1, to zmniejszamy jego wartość i kontunuujemy proces w ojcu tego węzła.

• Jeśli współczynnik wyważenia w węźle v wynosi -1, to konieczne jest

wyważanie: sprawdzamy współczynnik wyważenia w prawym nastęni-ku węzła v, powiedzmy węźle w.

– Jeśli współczynnik wyważenia w w jest równy 0, to stosujemy schemat RR i kończymy proces.

– Jeśli współczynnik wyważenia w w jest równy 1, to stosujemy schemat RR i rekurencyjnie kontunuujemy proces w ojcu węzła v – Jeśli współczynnik wyważenia w w jest równy -1, to stosujemy schemat RL i rekurencyjnie kontunuujemy proces w ojcu węzła v.

Analogiczne postępowanie stosujemy, gdy proces “wraca” z prawego poddrze-wa z sygnałem, że wysokość tego poddrzepoddrze-wa zmniejszyła się.

9.3 Zadania

1. Dla podanego ciągu kluczy zbudować drzewo BST: (4, 8, 2, 3, 7, 9, 1), a następnie usunąć kolejno elementy 8 i 4.

2. Zaprojektować samoorganizyjące się drzewo BST, czyli takie drzewo BST, by każdy wstawiany element był ostatecznie umieszczony w ko-rzeniu.

3. Dla ciągu kluczy (2, 4, 10, 5, 7, 6, 1) zbudować drzewo AVL. Podać ko-lejne kroki wstawiania i rodzaje wyważania.

4. Przedstawić w pseudokodzie przedstawione powyżej algorytmy wywa-żania węzła.

5. Dane jest AVL–drzewo postaci:

10

5 30

20

25 40 6

7 3

4 1

2

Usunąć z tego drzewa element x = 40.

Ćwiczenia 10

Powiązane dokumenty