Drzewa — podstawowe pojecia , • drzewo — graf reprezentujacy regularna, strukture, wskaźnikowa,, gdzie , każdy element zawiera dwa lub wiecej wskaźników (ponumerowanych) , do takich samych elementów; wezà , ly (albo wierzchoÃlki) grafu reprezentuja, elementy pamieciowe, a Ãluki reprezentuja, wskaźniki , • drzewo binarne — każdy element zawiera dokÃladnie dwa wskaźniki • korzeń — element drzewa, od którego zaczynaja, sie, wskaźniki do pozostaÃlych elementów • liście — elementy drzewa, których oba wskaźniki sa, puste (NIL) • wewnetrzne wezà , , ly drzewa — wezà , ly, które nie sa, ani liściami ani korzeniem • ścieżka — ciag zgodnie ze wskaźnikami od korzenia , wezà , , lów biegnacy do jakiegoś liścia • poddrzewo — drzewo, które jest caÃlkowicie zawarte w innym drzewie • rzad drzewa , drzewa — liczba wskaźników (≥ 2) w jednym weźle , (niektóre z nich sa, NIL) • wysokość — dÃlugość najdÃluższej ścieżki drzewa dlogk (N + 1)e ≤ hk (N ) ≤ N • waga — caÃlkowita liczba wezà , lów w drzewie Drzewa binarne 1 Struktury drzewiaste • grafy skierowane • zbiory zagnieżdżone º· A ´¹¸ Q ´ Q ´ Q ´ QQ º· +́ sº· B C ¹¸ ¹¸ Z ¢ B Z ¤ Z ¢ ¤ B Z ¢ BBN Z ¢® ¤²¤ ~ Z º· º· º· º· D E F G ¹¸ ¹¸ ¹¸ ¹¸ $ ' ' ' $ $ ¾» E ¾» ½¼ ¾» ¾» G F ½¼ D ½¼ ½¼ B C & & % & % A % • tekstowe listy symboli • typ danych drzew binarnych (A,(B,(D), (E), (F)), (), (C,(G), (), ())) TYPE T_Drzewo = ^T_Element; (A (B (D) (E) (F)) () (C (G) () ())) T_Element = RECORD info: T_info; lewe: T_Drzewo; prawe: T_Drzewo; END; (A,(B,(D),(E),(F)),(),(C,(G),(),())) (A,(B,(D),(E),(F)),(),(C,(G))) Drzewa binarne 2 Dodawanie elementu do drzewa (1) PROCEDURE DodajElement1(VAR drzewo: T_Drzewo; element: T_Drzewo); { wersja minimalna } BEGIN element^.lewe := drzewo; element^.prawe := NIL; drzewo := element; END; {DodajElement1} zmienne statyczne El: BD: pamieć , dynamiczna - info u lewe prawe u NIL ³³ u - info lewe prawe u ³³ ³³ ³ )³ info lewe prawe u ³ ³³ ) Drzewa binarne ³³ ³³ ) u PP P q u PP P PP q P info lewe prawe ³u ³³ ) u PP P q 3 diagram uproszczony tworzonego drzewa binarnego: ¾» El: ½¼ © © © © ¾» ©© ¼ © BD: ½¼ © HH HH ©© © ¾» ©© ¼ © HH ¾» H j ½¼ © HH © ¼ © H j ½¼ © HH © ¼ © j H ⇒ procedura DodajElement1 tworzy drzewa zdegenerowane! 6l ¢®¢ l 5 ¢®¢ l 4 ¢®¢ l 3 ¢®¢ l 2 ¢®¢ l 1 Drzewa binarne 4 Dodawanie elementu do drzewa (2) PROCEDURE DodajElement2(VAR drzewo: T_Drzewo; element: T_Drzewo); { wersja ulepszona } BEGIN IF drzewo = NIL THEN drzewo := element ELSE IF drzewo^.lewe = NIL THEN drzewo^.lewe = element ELSE IF drzewo^.prawe = NIL THEN drzewo^.prawe = element ELSE BEGIN XXX z m element^.lewe := drzewo; 12 © © element^.prawe := NIL; ¼© © 10m © HH drzewo := element; ©© HH ¼ © j m 8m 11 END © H © H HH © ¼© j m END; {DodajElement2} 6m 9 © H © H HH © ¼© j m m 4 7 © HH © HH ¼© © j m 1m 5 © H © H HH © ¼© j m 2m 3 ⇒ otrzymane drzewo nie jest wiele lepsze! Drzewa binarne 5 Dodawanie elementu do drzewa (3) PROCEDURE DodajElement3(VAR drzewo: T_Drzewo; element: T_Drzewo); { wersja "optymalna" } BEGIN IF drzewo = NIL THEN drzewo := element ELSE IF Waga(drzewo^.lewe) < Waga(drzewo^.prawe) THEN DodajElement3(drzewo^.lewe, element) ELSE DodajElement3(drzewo^.prawe, element); END; {DodajElement3} ⇒ procedura tworzy drzewa zrównoważone • Definicja: drzewo binarne nazywamy zrównoważonym albo: w peÃlni zrównoważonym, albo: dokÃladnie zrównoważonym, albo: zrównoważonym wagowo, jeżeli dla każdego wezà , la liczby wezà , lów w jego lewym i prawym poddrzewie (czyli wagi tych poddrzew) różnia, sie, co najwyżej o 1 Drzewa binarne 6 Przeszukiwanie drzew binarnych FUNCTION Wyszukaj(drzewo: T_Drzewo; elem_wzorc: T_Element; FUNCTION PorownajEl(e1,e2:T_Element):CHAR): T_Drzewo; {znajd.na drz.el.rownowazny danemu;zwraca wsk.el.,lub NIL gdy go nie ma} VAR test: T_Drzewo; BEGIN IF drzewo=NIL THEN Wyszukaj := NIL ELSE IF PorownajEl(elem_wzorc, drzewo^) = ’=’ THEN Wyszukaj := drzewo ELSE BEGIN test := Wyszukaj(drzewo^.lewe, elem_wzorc, PorownajEl); IF test <> NIL THEN Wyszukaj := test ELSE Wyszukaj := Wyszukaj(drzewo^.prawe, elem_wzorc, PorownajEl); END END; {Wyszukaj} Ćwiczenie: przepisać powyższa, funkcje, w wersji iteracyjnej! Drzewa binarne 7 Przegladanie drzew binarnych , PROCEDURE Przegladaj(Drzewo: T_Drzewo; PROCEDURE Op(e:T_Element)); BEGIN IF Drzewo<>NIL THEN BEGIN Op(Drzewo^); (* porzadek "preorder" *) Przegladaj(Drzewo^.lewe); Przegladaj(Drzewo^.prawe); END; END; {Przegladaj} • przydatne porzadki przegladania drzewa binarnego: , , ◦ preorder: najpierw korzeń, potem caÃle lewe poddrzewo, potem prawe ◦ inorder: najpierw lewe poddrzewo, nastepnie korzeń, na końcu prawe , ◦ postorder: najpierw lewe poddrzewo, potem prawe, na końcu korzeń Drzewa binarne 8 Drzewa uporzadkowane , • Definicja: drzewo binarne jest uporzadkowane gdy dla wszystkich wezà , , lów drzewa speÃlniona jest wÃlasność wszystkie elementy w lewym poddrzewie < korzeń < wszystkie elementy w prawym poddrzewie • zyskujemy na przeszukiwaniu: FUNCTION Wyszukaj(drzewo: T_Drzewo; elem_wzorc: T_Element; FUNCTION PorownajEl(e1,e2:T_Element):CHAR): T_Drzewo; BEGIN IF drzewo=NIL THEN Wyszukaj := NIL ELSE CASE PorownajEl(elem_wzorc, drzewo^) OF ’<’: Wyszukaj := Wyszukaj(drzewo^.lewe, elem_wzorc, PorownajEl); ’=’: Wyszukaj := drzewo; ’>’: Wyszukaj := Wyszukaj(drzewo^.prawe, elem_wzorc, PorownajEl); END; {CASE} END; {Wyszukaj} • wysokość drzewa binarnego o N wezà , lach: dlog2 (N + 1)e ≤ hN ≤ N Drzewa binarne 9 Dodawanie elementu do drzewa (4) jest bardzo podobne do wyszukiwania: • dodawanie uporzadkowane , praktycznie znajdujemy miejsce gdzie element powinien w drzewie sie, znaleźć, po czym go tam wklejamy PROCEDURE DodajElement4(VAR drzewo: T_Drzewo; element: T_Drzewo; FUNCTION PorownajEl(e1,e2:T_Element):CHAR); BEGIN IF drzewo=NIL THEN drzewo := Element ELSE CASE PorownajEl(element^, drzewo^) OF ’<’: DodajElement4(drzewo^.lewe, element, PorownajEl); ’=’: WRITELN(’Element juz jest na drzewie!’); ’>’: DodajElement4(drzewo^.prawe, element, PorownajEl); END; END; {DodajElement4} Drzewa binarne 10 Budowa drzew uporzadkowanych , • Od czego zależy wysokość drzewa utworzonego procedura, uporzadkowanego dodawania elementów? , Rozważmy przypadki skrajne: ◦ ciag , elementów: A B C D E F ... X Y Z ⇒ wysokość drzewa bedzie 26 (= N ) , ◦ ciag , elementów: M F T C I P W ... A L N Z ⇒ wysokość drzewa bedzie 5 (≈ log2(N )) , • ZÃla wiadomość: wysokość tak tworzonych drzew uporzadkowanych może , wahać sie, od log2(N ) do N • Dobra wiadomość: średnia oczekiwana wysokość drzewa tworzonego z przypadkowej sekwencji N elementów ≈ 1.4 × log2(N ) Drzewa binarne 11 Drzewa binarne 12 Usuwanie elementu z drzewa PROCEDURE UsunElement(VAR drzewo: T_Drzewo; element: T_Drzewo); FUNCTION PorownajEl(e1,e2:T_Element):CHAR); { wylacza z drzewa podany element } BEGIN IF drzewo=NIL THEN WRITELN(’Nie ma takiego elementu’) ELSE CASE PorownajEl(element^, drzewo^) OF ’<’: UsunElement(drzewo^.lewe, element, PorownajEl); ’>’: UsunElement(drzewo^.prawe, element, PorownajEl); ’=’: IF drzewo^.lewe=NIL THEN drzewo := drzewo^.prawe ELSE IF drzewo^.prawe=NIL THEN drzewo := drzewo^.lewe ELSE BEGIN DodajElement4(drzewo^.lewe, drzewo^.prawe, Porownaj); drzewo := drzewo^.lewe; QQ END; s²¯ QQ s E ±° ­J END; {CASE} ¡ @ ­DLJ ­ J ¡ @ ¡ ª @ R ­J END; {UsunElement} ­J ­J ­D J ­D J ­ LJ ­D J ­ PJ ­ PJ ⇒ niestety, metoda pogarsza zrównoważenie Drzewa binarne 13 Usuwanie elementu z drzewa (2) Q ¶³ Q s Q E • ciekawy pomysÃl: aby usunać , z drzewa element E, przenosimy na jego miejsce maksymalny element jego lewego poddrzewa (albo minimalny element poddrzewa prawego); w ten sposób sprowadzamy usuwanie wezà , la do usuwania liścia µ´ ¡ @ ¡ ¥º OD @ ¡ @ ¥ D ¡ @ ª ¡ @ R D ¥ ¢A ¢A D ¥ ¢ A ¢ A ¥ D A A ¢ ¢ D ¢ A ¥ A ¢ A ¥ ¢ D ¢ L A P AA ¢ ¢Dh ¥ h A A ¢ ¢ D D MAXD L MIND P ⇒ niestety, tej metody nie zawsze można użyć, bo nie zawsze MAXDL (albo MINDP ) bedzie liściem w drzewie , Q ¶³ Q s Q E µ´ ¡ 6@ @ ¡ @ ¡ • uzupeÃlnienie pomysÃlu: jeśli MAXDL nie jest liściem to po przeniesieniu go na miejsce wezà , la E usuwamy go z kolei wywoÃlaniem rekurencyjnym Drzewa binarne ¢ ¢ ¢ @ @ R ¢A ¢ A ¢ A D DP ¢ ¡ ª ¡ ¢A ¢ A ¢ A AhMAXD % L ¢¢ A L A ¢ A ¢ A A A A 14 Zastosowanie drzew uporzadkowanych , Podsumujmy: rozważamy struktury danych do przechowywania elementów np. jakiejś bazy danych. Dynamiczna, struktura, danych — odpowiednikiem statycznej tablicy nieuporzadkowanej — jest lista wskaźnikowa. Pomimo iż , tablica, w odróżnieniu od listy, zapewnia bezpośredni dostep , do wszystkich elementów, bez sekwencyjnego przeszukiwania, to bez uporzadkowania , elementów każde przeszukiwanie i tak musi być sekwencyjne. W takim razie dynamicznym odpowiednikiem tablic uporzadkowanych sa, , drzewa uporzadkowane. W jednych i drugich możliwe jest niesekwencyjne , wyszukanie konkretnego elementu. Jednak w przypadku drzew uporzadkowanych liczba (albo czas) operacji niezbednych do dotarcia do , , elementu zależy od zrównoważenia drzewa, nad którym nie umiemy zapanować (na razie). Jednak zagadnienie równoważenia drzew uporzadkowanych jest trudne — , nie jest znana praktyczna metoda tworzenia drzew uporzadkowanych i , jednocześnie w peÃlni zrównoważonych. Podobnie nie istnieje żadna efektywna metoda równoważenia już zbudowanego drzewa. Jak sie, okaże, najlepszym rozwiazaniem sa, drzewa cześciowo zrównoważone. , , Drzewa binarne 15 Zagadnienie równoważenia drzew z • rozważmy dodanie pojedynczego wezà , , la do drzewa uporzadkowanego zachowaniem równowagi ¶³ ¶³ µ´ ©© HHH © ¶³ ¼ © j¶³ H µ´ ©© HHH © ¶³ ¼ © j¶³ H I E µ´ ¡ @ ¶³ ¶³ ¡ ª @ R C G M µ´ ¡ @ ¶³ ¶³ ª ¡ @ R K O H D L µ´ ¡ @ ¶³ ¶³ ¡ ª @ R B µ´ ¡ @ ¶³ ¶³ ª ¡ @ R F J N µ´ µ´ µ´ µ´ £ B £ B £ B £ ¶³ ¶³ ¶³ ¶³ £° ¶³ BN £° ¶³ BN £° ¶³ BN £° µ´ µ´ µ´ µ´ £ B £ B £ B £ B ¶³ ¶³ ¶³ ¶³ £° ¶³ BN £° ¶³ BN £° ¶³ BN £° ¶³ BN µ´ µ´ µ´ µ´ µ´ µ´ µ´ µ´ µ´ µ´ µ´ µ´ µ´ µ´ µ´ B D F H J L N A C E G I K M O ⇒ struktura drzewa ulegÃla caÃlkowitej zmianie, żaden wezeà , l nie pozostaÃl na swoim miejscu Drzewa binarne 16 Inne zastosowania — drzewa wyrażeń Drzewa binarne sa, przydatne w wielu zastosowaniach, nie tylko do przechowywania elementów jakiejś bazy danych. Jednym z nich sa, drzewa wyrażeń reprezentujace wyrażenia algebraiczne wyrażone w jakimś jezyku , , zawierajacym operatory i operandy. Takie drzewa byÃly użyte do , reprezentacji wyrażeń Pascala — dowolne wyrażenie można przedstawić za pomoca, drzewa, którego liście reprezentuja, zmienne i staÃle, a wezà , ly wewnetrzne operatory. , Drzewa binarne 17 Drzewa binarne 18