Drzewa: BST, kopce - Letnie Warsztaty Matematyczno

Transkrypt

Drzewa: BST, kopce - Letnie Warsztaty Matematyczno
Letnie Warsztaty Matematyczno-Informatyczne
Algorytmy i struktury danych
Drzewa: BST, kopce
Drzewa: BST, kopce
Definicja drzewa
Drzewo (ang. tree) to nieskierowany, acykliczny, spójny graf.
Drzewo może być ukorzenione (ang. rooted), to znaczy posiadać
korzeń (ang. root) – jeden wyróżniony wierzchołek.
Drzewa: BST, kopce
Definicja drzewa
W drzewie ukorzenionym możemy definiować relacje między
wierzchołkami. Jeżeli na drodze z korzenia do jakiegoś wierzchołka
u znajduje się przed v , to u jest przodkiem v , a v jest potomkiem
u.
Bezpośredni przodek to rodzic (ang. parent), a bezpośredni
potomek to dziecko (ang. child). Wierzchołki posiadające
wspólnego rodzica to bracia (ang. sibling ). Wierzchołki
nieposiadające dzieci nazywamy liśćmi (ang. leaf ).
Drzewa: BST, kopce
Drzewa binarne
Jeżeli w drzewie ukorzenionym każdy wierzchołek posiada co
najwyżej 2 dzieci, to takie drzewo nazywamy binarnym (ang. binary
tree).
Drzewa: BST, kopce
Drzewa przeszukiwań binarnych
Drzewo przeszukiwań binarnych (ang. binary search tree, BST )
jest strukturą danych, będącą specjalnym przypadkiem drzewa
binarnego.
Każdy z wierzchołków w takim drzewie posiada przypisaną
wartość. Dodatkowo ułożenie tych wartości musi być zgodne z
następującą regułą:
Wszystkie wartości w lewym poddrzewie danego wierzchołka
muszą być mniejsze od wartości tego wierzchołka. Podobnie
wszystkie wartości w jego prawym poddrzewie muszą być od
wartości tego wierzchołka większe.
Drzewa: BST, kopce
Drzewa przeszukiwań binarnych
Drzewa przeszukiwań binarnych mogą zostać użyte do
zaimplementowania zbioru.
Operacje Insert, Member? i Delete mają średnią złożoność
obliczeniową O(log n), zaś pesymistyczną O(n).
Drzewa: BST, kopce
Drzewa przeszukiwań binarnych
procedure Insert(T , v )
if v < T .value then
if T .left = nil then
T .left ← BST − Node(v )
else
Insert(T .left, v )
end if
else
if T .right = nil then
T .right ← BST − Node(v )
else
Insert(T .right, v )
end if
end if
end procedure
Drzewa: BST, kopce
Drzewa przeszukiwań binarnych
procedure Member?(T , v )
if T = nil then
return false
else if v = T .value then
return true
else if v < T .value then
return Member?(T .left, v )
else
return Member?(T .right, v )
end if
end procedure
Drzewa: BST, kopce
Kopiec binarny
Kopiec binarny (ang. binary heap) to również struktura danych
będąca specjalnym przypadkiem drzewa binarnego. Tak jak w
przypadku BST, wszystkie wierzchołki posiadają przypisane
wartości.
Oprócz tego kopiec musi być drzewem prawie pełnym, a wartości w
nim muszą spełniać regułę kopca, tj. wszyscy potomkowie danego
wierzchołka muszą mieć wartości większe od niego.
Drzewa: BST, kopce
Kopiec binarny
Kopiec binarny może być użyty do zaimplementowania kolejki
priorytetowej, w której operacje Insert, Extract-Minimum i
Delete mają złożoność obliczeniową O(log n), a Top – O(1).
Drzewa: BST, kopce
Kopiec dwumianowy
Kopiec dwumianowy (ang. binomial heap) jest strukturą danych
opartą na lesie (ang. forest), czyli zbiorze drzew.
Umożliwia implementację kolejki priorytetowej, w której operacje
Insert, Extract-Minimum i Delete mają złożoność
obliczeniową O(log n), Top – O(1), a do tego złączenie dwóch
kopców jest możliwe w czasie O(log n) (w odróżnieniu od kopca
binarnego, gdzie ta operacja zajmuje czas liniowy).
Letnie Warsztaty Matematyczno-Informatyczne
Algorytmy i struktury danych
Wyszukiwanie wzorca w tekście
Wyszukiwanie wzorca w tekście
Istota problemu
Mamy dane dwa ciągi znaków: tekst T (ang. haystack) i wzorzec
P (ang. needle). Oba z nich są tablicami.
Istotą problemu jest znalezienie wszystkich indeksów w tekście
takich, że od tego miejsca tekst jest identyczny ze wzorcem (do
końca wzorca).
Wyszukiwanie wzorca w tekście
Istota problemu
Przykładowo, mając dany tekst: „abrakadabra” i wzorzec „ra”,
wynikami będą 2 i 9 (pamiętaj, że indeksy zaczynają się od 0).
Dla tekstu: „aaaa” i wzorca „aa”, wynikami będą 0, 1 i 2.
Wyszukiwanie wzorca w tekście
Algorytm naiwny
Mając dany indeks możemy łatwo sprawdzić, czy jest on
poprawnym rozwiązaniem, porównując kolejne znaki w T ze
znakami w P. Zajmuje to czas O(|P|).
Algorytm naiwny sprawdza w ten sposób każdy możliwy indeks
(O(|T |) sprawdzeń), dając całkowitą złożoność obliczeniową
O(|P||T |).
Algorytm ten można przyspieszyć, przerywając sprawdzanie w
momencie pierwszego różniącego się znaku, jednak pesymistyczna
złożoność obliczeniowa zostaje taka sama.
Wyszukiwanie wzorca w tekście
Algorytm Rabina-Karpa
Algorytm Rabina-Karpa również opiera się na sprawdzaniu
możliwych indeksów, jak algorytm naiwny, jednak zmniejsza liczbę
potencjalnych kandydatów, używając funkcji haszującej.
Przed wykonaniem właściwego sprawdzenia obliczany jest hasz
wzorca, a potem dla każdego indeksu obliczany jest hasz |P|
następnych znaków. Właściwe sprawdzenie wykonywane jest tylko
w momencie zgodności haszy.
Wyszukiwanie wzorca w tekście
Algorytm Rabina-Karpa
Wydawać by się mogło, że nie poprawia to złożoności obliczeniowej
(koszt liczenia haszu również wynosi O(|P|)).
Istota optymalizacji polega jednak na tym, że wykorzystujemy taką
funkcję haszującą, której wartość w indeksie i można szybko
obliczyć na podstawie wartości w indeksie i − 1 (tzw. rolling hash).
Wyszukiwanie wzorca w tekście
Automaty skończone
Do rozwiązania problemu wyszukiwania wzorca w tekście można
użyć również automatów skończonych.
Automat skończony to graf skierowany, w którym krawędzie mają
dodatkowo przypisane symbole (lub grupy symboli) i nazywa się je
przejściami. Wierzchołki nazywamy stanami. Jeden ze stanów jest
stanem początkowym, jeden jest stanem akceptującym.
Wyszukiwanie wzorca w tekście
Automaty skończone
Mamy dany tekst i automat skończony zbudowany na podstawie
wzorca. Zaczynając od stanu początkowego, przechodzimy między
stanami, wybierając przejścia zgodnie z kolejnymi znakami tekstu.
Jeżeli znajdziemy się w stanie akceptującym oznacza to, że
znajdujemy się w ostatnim znaku dopasowania.

Podobne dokumenty