background image

Algorytmy i struktury danych

Algorytmy i struktury danych

wykład 8

 Słowniki 

wykładowca:  Wojciech Folta

background image

Niniejsza prezentacja nie 

wyczerpuje zakresu 

tematycznego przedmiotu: 

„Algorytmy i struktury 

danych” nie stanowi też 

pełnej wiedzy na 

określony temat.

Slajdy prezentacji są 

jedynie uzupełnieniem 

wykładu.

Wojciech Folta

background image

Słownik

to struktura danych 

reprezentująca dynamiczny

(tzn. mogący zmieniać się w czasie)

zbiór elementów (kluczy) 

background image

Na słowniku

można wykonywać następujące operacje: 

-

Find(S,x): zwraca klucz x ze słownika S, 
albo NULL jeśli tego klucza nie ma w 
słowniku;

-

Insert(S,x): wstawia klucz x do słownika 
S;

-

Delete(S,x): usuwa klucz x ze słownika S.

background image

Słownik

implementować można za pomocą 

drzew.

W uniwersum wszystkich 
potencjalnych elementów 
słownika wprowadza się liniowy 
porządek, 
a podstawowym mechanizmem
w zarządzaniu słownikiem jest 
porównywanie kluczy. 

background image

Drzewa BST

Drzewa poszukiwań binarnych

(BST, od ang. Binary Search Tree) 

pesymistyczny koszt 

wymienionych wyżej operacji 

słownikowych

(Find, Insert, Delete)

jest proporcjonalny do wysokości 

drzewa. 

background image

Drzewa BST

Kształt drzewa - więc i jego 

wysokość - zależy od ciągu 

wykonywanych na nim 

operacji. 

Nietrudno podać przykład ciągu 

operacji konstruującego 

drzewo o      węzłach

i wysokości   

background image

Drzewa AVL

(od Adelson-Velskij, Landis) 

do warunku BST umożliwiającego
wyszukiwanie w czasie proporcjonalnym do
wysokości drzewa, dołożono warunek
zrównoważenia
, gwarantujący, że wysokość
drzewa zawsze pozostaje logarytmiczna
względem jego rozmiaru:
W każdym węźle wysokości obu jego 

poddrzew różnią się co najwyżej o 1.

background image

Drzewa AVL

W każdym węźle przechowywany jest dodatkowy 

atrybut, 

"współczynnik zrównoważenia", 
przyjmujący wartości:

"-" jeśli lewe poddrzewo jest o 1 wyższe niż prawe;

"0" jeśli oba poddrzewa są takiej samej wysokości;

"+" jeśli prawe poddrzewo jest o 1 wyższe niż 

lewe.

background image

Drzewa AVL

Problem: 

wykonywać wszystkie operacje 
słownikowe na drzewach AVL z 
kosztem co najwyżej 
proporcjonalnym do wysokości 
drzewa 
(czyli logarytmicznym). 

background image

Operacja Find

Operacja Find

jest wykonywana tak samo jak w zwykłych 
drzewach BST: schodzimy w dół drzewa po 
ścieżce od korzenia do szukanego węzła 
(albo do węzła zewnętrznego NULL), o 
wyborze lewego lub prawego poddrzewa 
na każdym poziomie rozstrzygając na 
podstawie porównania szukanego klucza z 
zawartością aktualnego węzła na ścieżce. 

background image

Operacje Insert i Delete

Operacje Insert i Delete

są bardziej skomplikowane, 
ponieważ wymagają aktualizowania 
współczynników zrównoważenia, a 
niekiedy również przywracania 
warunku AVL. 

background image

Rotacje

Do zmiany kształtu drzewa w celu jego 
zrównoważenia służy mechanizm rotacji
Po wykonaniu rotacji pojedynczej ROT1  
węzła   z jego ojcem   oba węzły zamieniają 
się rolami ojciec-syn, przy zachowaniu 
własności BST: 

background image

Rotacja podwójna

rotacji podwójnej ROT2(p,q,r) uczestniczą 

trzy węzły: 

p

, jego ojciec 

q

  i jego dziadek 

r

przy czym albo 

p

 jest lewym synem, a 

q

 

prawym (ten właśnie przypadek rozważamy), 
albo odwrotnie.

Po rotacji 

p

 staje się korzeniem całego drzewa, 

przy zachowaniu własności BST: 

background image

Rotacja podwójna

rotacja podwójna ROT2(p,q,r) jest
w rzeczywistości złożeniem dwóch rotacji 
pojedynczych ROT1(p,q) i ROT1(p,r).
Koszt wykonania jednej rotacji jest stały. 

background image

Wstawianie węzłów w drzewach 

AVL

Podczas operacji Insert tak samo jak dla 

zwykłych drzew BST schodzimy po 
ścieżce od korzenia w dół do węzła 
zewnętrznego NULL i w jego miejscu 
tworzymy nowy liść ze wstawianym 
kluczem. 

Następnie wracamy po ścieżce do 

korzenia, aktualizując współczynniki 
zrównoważenia. 

background image

Wstawianie węzłów w drzewach 

AVL

Jeśli stwierdzamy, że wysokość poddrzewa wzrosła 

(mogła wzrosnąć co najwyżej o 1!), kontynuujemy 

marsz w górę drzewa. Jeśli w wyniku wzrostu 

wysokości jednego z poddrzew aktualnie 

rozważanego węzła został w nim zaburzony 

warunek AVL, to przywracamy go za pomocą 

rotacji. Z dokładnością do symetrii mamy wtedy 

dwa przypadki (w obydwu zakładamy, że 

p

 jest 

węzłem, w którym zaburzony został warunek AVL 

wskutek wzrostu wysokości jego prawego 

poddrzewa o korzeniu 

q

; w pierwszym przypadku 

zakładamy, że wzrosła wysokość prawego 

poddrzewa 

q

, a w drugim - lewego) 

background image

Wstawianie węzłów w drzewach 

AVL

Zauważmy, że w 
obydwu 
przypadkach po 
rotacji 
wysokość 
całego 
poddrzewa jest 
taka sama jak 
przed całą 
operacją, zatem 
wykonanie 
jednej rotacji 
(pojedynczej lub 
podwójnej) 
kończy operację 

Insert.

 

background image

Operację Delete, 

tak samo jak w przypadku usuwania ze 

zwykłego drzewa BST, sprowadzamy 

do przypadku usuwania węzła 

mającego co najwyżej jednego syna. 

Usuwanie węzłów w 

drzewach AVL

background image

W drzewie AVL albo sam węzeł, albo jego 

jedyny syn musi być liściem. Po 
usunięciu węzła wracamy po ścieżce do 
korzenia, aktualizując współczynniki 
zrównoważenia. 

Usuwanie węzłów w 

drzewach AVL

background image

jeśli stwierdzamy, że wysokość poddrzewa 

spadła (mogła spaść co najwyżej o 1!), to 

kontynuujemy marsz w górę drzewa. Jeśli 

w wyniku spadku wysokości jednego z 

poddrzew aktualnie rozważanego węzła 

został w nim zaburzony warunek AVL, to 

przywracamy go za pomocą rotacji. 

Usuwanie węzłów w 

drzewach AVL

background image

Z dokładnością do symetrii mamy wtedy dwa 

przypadki (w obydwu zakładamy, że 

p

 jest 

węzłem, w którym zaburzony został 

warunek AVL wskutek spadku wysokości 

jego lewego poddrzewa, a 

q

 jest 

korzeniem prawego poddrzewa 

p

; w 

pierwszym przypadku zakładamy, że 

współczynnik zrównoważenia w 

q

 przed 

operacja Delete był równy "0" lub "+", a w 

drugim, że "-").

Usuwanie węzłów w 

drzewach AVL

background image

Usuwanie węzłów w 

drzewach AVL

a

background image

Usuwanie węzłów w 

drzewach AVL

a

W pierwszym przypadku, jeśli 

współczynnik zrównoważenia w 

q

 przed 

operacją Delete był równy "0", po 

rotacji wysokość całego poddrzewa jest 

taka sama jak przed całą operacją, 

wykonanie rotacji kończy więc operację 

Delete. Jeśli jednak współczynnik był 

równy "+", wysokość spada o 1. W 

przypadku 2 wysokość całego 

poddrzewa również spada o 1 i trzeba 

kontynuować marsz w stronę korzenia. 

Operacja Delete może zatem wymagać 

wykonania logarytmicznej liczby rotacji. 

background image

Samoorganizujące się 

drzewa BST 

Sleator i Tarjan [ST]

Opisali drzewa splay - czyli drzewa 
BST, w których wykorzystuje się 
rotacje do ich równoważenia, jednak 
nie trzeba przechowywać żadnych 
dodatkowych atrybutów w węzłach. 

background image

Samoorganizujące się 

drzewa BST 

koszt zamortyzowany

operacji słownikowych w tej strukturze 

danych

jest logarytmiczny. 

background image

Procedura splay ( S ,  ) 

przekształca drzewo S w taki sposób, że jego 

korzeniem staje się węzeł z kluczem  

(albo - jeśli klucza  nie ma w S – to w węzeł 

z kluczem najbliższym  ).

background image

Procedura splay ( S ,  ) 

Jeżeli  jest w S:

korzeniem staje się węzeł z kluczem 
 

jeśli klucza  nie ma w S:

węzeł z kluczem y takim, że w S nie 
ma żadnego klucza pomiędzy
min (  , y )  a max (  , y ) 

background image

Procedura splay ( S ,  ) 

Operacja Find ( S ,  )

sprowadza się do wywołania

splay ( S ,  ) 

i sprawdzenia, czy  jest w korzeniu. 

background image

operacja Insert ( S ,  )

 

W celu wykonania Insert( S ,  ) wywołuje się 

najpierw splay( S ,  ), w wyniku czego w korzeniu 

znajduje się klucz 

y

; bez straty ogólności można 

przyjąć, że 

y < 

 . Odcinamy prawe poddrzewo 

R

 

węzła 

y

, jego ojcem (a zarazem nowym korzeniem) 

zostaje węzeł z kluczem 

, którego prawym 

poddrzewem czynimy 

R

background image

operacja 

Delete

 ( S ,  )

 

Operację Delete( S ,  ) zaczynamy od wywołania 
splay( S ,  ), sprowadzając usuwany klucz do 

korzenia. Niech 

L

 i 

R

 będą odpowiednio lewym i 

prawym poddrzewem uzyskanego drzewa. Odcinamy 

korzeń i - jeśli 

L

 jest niepuste - wywołujemy splay(

L

 , 

 ), a następnie przyłączamy 

R

 jako prawe 

poddrzewo korzenia. 

background image

Definicja procedury splay 

( S ,  ) 

Najpierw szukany jest węzeł 

v

 z kluczem  w drzewie 

S

tak jak w zwykłym drzewie BST (jeśli klucza  nie ma 

w drzewie, to jako 

v

 bierzemy ostatni węzeł na 

ścieżce przed węzłem zewnętrznym NULL). 

Następnie, dopóki 

v

 nie stanie się korzeniem, 

wykonujemy sekwencję rotacji zgodnie z poniższym 

schematem: 

• Jeżeli 

v

 jest synem korzenia 

w

, to wykonuje 

ROT1

(v,w)

.

• Jeżeli 

v

 ma ojca 

w

 i dziadka 

u

, przy czym oba węzły i 

są lewymi synami, albo oba prawymi, to wykonujemy 

ROT1

(w,u)

, a następnie ROT1

(v,w)

.  

• Jeżeli 

v

 ma ojca 

w

 i dziadka 

u

, przy czym jeden z 

węzłów 

v

 jest lewym synem, a drugi 

w

 prawym, to 

wykonujemy ROT1

(v,w)

, a następnie ROT1

(v,u)

 (czyli 

w sumie rotację podwójną ROT2 

(v,w,u) 

). 

background image

Definicja procedury splay 

( S ,  ) 

1. Jeżeli 

v

 jest synem korzenia 

w

, to wykonuje 

ROT1

(v,w)

.

2. Jeżeli 

v

 ma ojca 

w

 i dziadka 

u

, przy czym oba 

węzły i są lewymi synami, albo oba prawymi, to 
wykonujemy ROT1

(w,u)

, a następnie ROT1

(v,w)

.  

background image

Definicja procedury splay 

( S ,  ) 

3. Jeżeli 

v

 ma ojca 

w

 i dziadka 

u

, przy czym jeden z 

węzłów 

v

 jest lewym synem, a drugi 

w

 prawym, 

to wykonujemy ROT1

(v,w)

, a następnie ROT1

(v,u)

 

(czyli w sumie rotację podwójną ROT2 

(v,w,u) 

). 

background image

B – drzewa 

Drzewa BST (nawet w wersjach 
zrównoważonych), nie najlepiej nadają się 
do przechowywania na dysku komputera.

 

Specyfika pamięci dyskowej polega na tym, że czas 
dostępu do niej jest znacznie (o kilka rzędów wielkości) 
dłuższy niż do pamięci wewnętrznej (RAM), a odczytu i 
zapisu danych dokonuje się większymi porcjami 
(zwanymi blokami lub stronami). 
Chaotyczne rozmieszczenie węzłów drzewa BST na 
dysku bez brania pod uwagę struktury tego rodzaju 
pamięci prowadzi do większej niż to naprawdę konieczne 
liczby dostępów. 

background image

B – drzewa 

Wynalezione na początku lat 
sześćdziesiątych XX wieku przez:

Bayera i MacCreighta [BM] 

B-drzewa to drzewa poszukiwań 
wyższych rzędów

background image

B – drzewa 

W węźle drzewa BST mamy dwa wskaźniki do lewego i prawego syna i 
jeden klucz, który rozdziela wartości przechowywane w lewym i prawym 
poddrzewie.

W węźle drzewa poszukiwań rzędu 

l

 jest 

l

 wskaźników 

do synów 

p

1

, p

2

, ... , p

l

 oraz 

l-1

 kluczy 

k

1

< k

2

< ... < k

l-1

 , 

które rozdzielają elementy poszczególnych poddrzew: 
wartości w poddrzewie wskazywanym przez 

p

i

 muszą 

mieścić się w przedziale otwartym 

(k

i-1

..k

i

)

 dla 

 i 

 l

 

(przyjmując, że 

k

0

=-

 oraz 

k

l

=

 ). 

Rozmiar węzła w B-drzewie dobiera się zwykle tak, aby 
możliwie dokładnie wypełniał on stronę na dysku - pojedynczy 
węzeł może zawierać nawet kilka tysięcy kluczy i wskaźników. 
Zachowanie zrównoważenia umożliwione jest dzięki 
zmiennemu stopniowi wypełnienia węzłów. 

background image

Definicja B – drzewa rzędu m 

(m3)

1. Korzeń jest liściem, albo ma od 

2

 do 

m

 synów.

2. Wszystkie liście są na tym samym poziomie.
3. Każdy węzeł wewnętrzny oprócz korzenia ma 

od 

[m/2]

 do 

m

 synów. Węzeł mający 

l

 synów 

zawiera 

l-1

 kluczy.

4. Każdy liść zawiera od 

[m/2]-1

 do 

m-1

 kluczy.

background image

Definicja B – drzewa rzędu m 

(m3)

Warunki (3) i (4) gwarantują wykorzystanie 
przestrzeni dysku przynajmniej w ok. 50%,
a warunek (2) - niewielką wysokość drzewa 
(w najgorszym razie ok. 

log

m/2

 n/(m/2)

, a w 

najlepszym ok. 

log

m

 n/m) 

dla drzewa 

zawierającego kluczy). 

background image

Definicja B – drzewa rzędu m 

(m3)

Koszt operacji słownikowych na B-
drzewach jest co najwyżej proporcjonalny 
do wysokości drzewa.
Na przykład, można dla 

m = 101

 znaleźć 

jeden spośród miliona kluczy w drzewie 
przy pomocy trzech odwołań do węzłów. 

background image

Przykładowe B – drzewo rzędu 

3

zwane też 2-3 drzewem
(1-2 klucze i 2-3 synów w węźle): 

background image

Operacja Find w B – drzewie

Jest analogiczna jak w drzewach BST. 
Poszukiwanie klucza 

 rozpoczynamy od korzenia.

W aktualnym węźle zawierającym klucze 

k

1

k

2

< ... < k

l-1

 szukamy klucza 

 

(sekwencyjnie lub 

binarnie).
Jeśli to poszukiwanie kończy się niepowodzeniem, 

to albo - jeśli aktualny węzeł jest liściem - klucza 

 w ogóle nie ma w drzewie, albo, mając 

wyznaczony indeks 

i

 o tej własności, że 

k

i-1 

 < 

k

i

 (przy założeniu, że 

k

0

=-

 oraz 

k

l

=

 ), 

rekurencyjnie poszukujemy klucza 

 w 

poddrzewie o korzeniu wskazywanym przez 

p

i

background image

Operacja Insert ( S , 

 ) w B – 

drzewie

Operacja Insert ( S , 

 ) zaczyna się od 

odszukania (jak w operacji Find) liścia, w 

którym powinien znaleźć się wstawiany klucz. 

Jeśli ten liść nie jest całkowicie wypełniony 

(czyli zawiera mniej niż 

m-1

 kluczy), po prostu 

wstawia się 

 w odpowiednie miejsce w węźle, 

przesuwając część kluczy (koszt tego zabiegu 

jest pomijalnie mały w porównaniu z kosztem 

odczytu i zapisu węzła na dysk).
W przeciwnym razie po dołożeniu nowego 

klucza węzeł jest przepełniony i trzeba 

przywrócić warunek zrównoważenia. 

background image

Operacja Insert ( S , 

 ) w B – 

drzewie

Najpierw próbujemy wykonać przesunięcie kluczy: ta 

metoda daje się zastosować, jeśli któryś z dwóch 

sąsiednich braci przepełnionego węzła (który nie musi 

koniecznie być liściem) ma mniej niż 

m-1

 kluczy. Dla 

ustalenia uwagi przyjmijmy, że jest to lewy brat i 

oznaczmy go przez 

p

, sam przepełniony węzeł przez 

q

, a 

klucz rozdzielający wskaźniki do 

p

 i 

q

 w ich ojcu przez 

k

Klucz 

k

 przenosimy z ojca do 

p

 jako największy klucz w 

tym węźle, w jego miejsce w ojcu przenosimy najmniejszy 

klucz z 

q

, po czym skrajnie lewe poddrzewo 

p

 czynimy 

skrajnie prawym poddrzewem 

q

.

Przesunięcie kluczy w prawo wykonuje się symetrycznie. 
Po takim zabiegu warunki równowagi zostają odtworzone 

i cała operacja się kończy. 

background image

Operacja Insert ( S , 

 ) w B – 

drzewie

Jeśli przepełniony węzeł nie ma niepełnego sąsiada, 

to wykonujemy rozbicie węzła. Listę kluczy dzielimy 

na trzy grupy: 

[m-1]/2

 najmniejszych kluczy, jeden 

klucz środkowy oraz 

[m-1]/2 = [m/2]+1

 największych 

kluczy. Z pierwszej i trzeciej grupy tworzymy nowe 

węzły, a środkowy klucz wstawiamy do ojca (co może 

spowodować jego przepełnienie i konieczność 

kontynuowania procesu przywracania 

zrównoważenia o jeden poziom wyżej) i odpowiednio 

przepinamy poddrzewa. Kiedy następuje 

przepełnienie korzenia, rozbijamy go na dwa węzły i 

tworzymy nowy korzeń mający dwóch synów (to jest 

właśnie powód, dla którego korzeń stanowi wyjątek 

w warunku (3)) - to jest jedyna sytuacja, w której 

wysokość B-drzewa się zwiększa. 

background image

Operacja Delete (S , 

 ) w B – 

drzewie

Operację Delete  również zaczynamy od 

odszukania węzła z kluczem do usunięcia. 

Poddrzewa rozdzielane przez klucz 

 

oznaczmy przez 

p

 i 

q

Tak jak przy usuwaniu z BST, w miejsce 

 

przenosimy - znajdujący się w liściu - 

największy klucz z 

p

 (albo największy z 

q

). 

Lukę po przeniesionym kluczu niwelujemy 

zsuwając pozostałe. Jeśli jest ich co najmniej 

[m/2]-1

, cała operacja jest zakończona, 

natomiast w razie niedoboru w celu 

przywrócenia równowagi musimy dokonać 

przesunięcia kluczy albo sklejenia węzłów

background image

Operacja Delete (S , 

 ) w B – 

drzewie

Jeśli któryś z dwóch sąsiednich braci węzła 
z niedoborem ma co najmniej o jeden klucz 
więcej niż dozwolone minimum, to - 
podobnie jak przy wstawianiu - przesuwamy 
skrajny klucz z niego do ojca w miejsce 
klucza rozdzielającego braci, który z kolei 
wędruje do węzła z niedoborem. 

background image

Operacja Delete (S , 

 ) w B – 

drzewie

Niemożność wykonania przesunięcia kluczy 
oznacza, że brat węzła z niedoborem ma 
dokładnie 

[m/2]-1

 kluczy. Sklejamy te dwa węzły 

w jeden, wstawiając jeszcze pomiędzy ich klucze 
klucz rozdzielający z ojca i odpowiednio 
przepinając poddrzewa. Powstaje w ten sposób 
węzeł o 

2*[m/2]-2 

  m-1

 kluczach, a z ojca 

ubywa jeden klucz, co może spowodować w nim 
niedobór i konieczność kontynuowania procesu 
przywracania zrównoważenia wyżej w drzewie. 

background image

Operacja Delete (S , 

 ) w B – 

drzewie

Jeśli korzeń traci swój jedyny klucz, 
usuwamy ten węzeł, a jego jedynego syna 
czynimy nowym korzeniem - to jest jedyna 
sytuacja, w której wysokość B-drzewa 
maleje. 

background image

G. M. Adelson-Velskij, E. M. Landis, An algorithm for 

the organization of information, Soviet Math. 

Doklady 3, 1962, 1259-1263.

R. Bayer, E. M. McCreight, Organization and 

Maintenance of Large Ordered Indexes, Acta 

Informatica 1, 1972, 173-189.

Thomas H. Cormen, Charles E. Leiserson, Ronald L. 

Rivest, Clifford Stein, 'Wprowadzenie do 

algorytmów', WNT, Warszawa 2004.

D.D. Sleator, R.E. Tarjan, Self-Adjusting Binary 

Search Trees, Journal of the ACM 32:3, 1985, 652-

686. Źródło: 

http://wazniak.mimuw.edu.pl/index.php?

title=Algorytmy_i_struktury_danych/Kolejki_prioryte

towe

Literatura


Document Outline