Wykład 2 Drzewa poszukiwań binarnych (BST)

Transkrypt

Wykład 2 Drzewa poszukiwań binarnych (BST)
Wykład 2
Drzewa poszukiwań
binarnych (BST)
1
O czym będziemy mówić
Definicja
Operacje na drzewach BST:
– Search
– Minimum, Maximum
– Predecessor, Successor
– Insert, Delete
Struktura losowo budowanych drzew BST
2
Wprowadzenie
Poszukujemy dynamicznego ADT, który efektywnie będzie obsługiwał
następujące operacje:
– Wyszukiwanie elementu (Search)
– Znajdowanie Minimum/Maximum
– Znajdowanie poprzednika/następnika (Predecessor/Successor)
– Wstawianie/usuwanie elementu (Insert/Delete)
Wykorzystamy drzewo binarne! Wszystkie operacje powinny zajmować
czas Θ(lg n)
Drzewo powinno być zawsze zbalansowane – inaczej czas będzie
proporcjonalny do wysokości drzewa (gorszy od O(lg n))!
3
Drzewo poszukiwań binarnych (binary search tree)
Struktura drzewa z korzeniem
Każdy węzeł x posiada pola left(x), right(x), parent(x), oraz key(x).
Własność drzewa BST:
Niech x będzie dowolnym węzłem drzewa, natomiast niech y będzie
należał do poddrzewa o korzeniu w x wtedy:.
– Jeżeli należy do lewego poddrzewa to: key(y) ≤ key(x)
– Jeżeli należy do prawego poddrzewa to : key(y) > key(x)
4
Przykład BST
5
2
3
2
7
5
3
7
8
5
8
5
Metody przechodzenia przez drzewo :
In-order, pre-order, post-order
5
Poszukiwanie w drzewie BST
Tree-Search(x,k)
if x = null or k = key[x]
then return x
if k < key[x]
then return Tree-Search(left[x],k)
else return Tree-Search(right[x],k)
Tree-Search(x,k)
while x ≠ null and k ≠ key[x]
do if k < key[x]
then x left[x]
else x right[x]
return x
rekurencyjnie
iteracyjnie
złożoność: O(h)
6
Przykład
Poszukiwany klucz: 13
7
Przechodzenie przez wszystkie węzły drzewa
Inorder-Tree-Walk(x)
if x ≠ null
then Inorder-Tree-Walk(left[x])
print key[x]
Inorder-Tree-Walk(right[x])
złożoność: Θ(n)
8
Odnajdowanie minimum i maksimum
Tree-Minimum(x)
while left[x] ≠ null
do x left[x]
return x
Tree-Maximum(x)
while right[x] ≠ null
do x right[x]
return x
złożoność: O(h)
9
Przykład – minimum
10
Odnajdowanie następnika
Następnikiem x nazywamy najmniejszy element y wśród elementów
większych od x
Następnik może zostać odnaleziony bez porównywania kluczy. Jest
to :
1.
2.
3.
null jeśli x jest największym z węzłów.
minimum w prawym poddrzewie t jeśli ono istnieje.
najmniejszy z przodków x, dla których lewy potomek jest
przodkiem x.
11
Odnajdowanie następnika
x
z
y
minimum w prawym poddrzewie t
x
najmniejszy z przodków x,
dla których lewy potomek
jest przodkiem x
12
Odnajdowanie następnika
Tree-Successor(x)
if right[x] ≠ null
// przypadek 2
then return Tree-Minimum(right[x])
y parent[x]
while y ≠ null and x = right[y]
// przypadek 3
do x y
y parent[y]
return y
13
Przykład
Poszukajmy następników dla 15 (przyp. 2), 13 (przyp. 3)
14
Wstawianie elementów
Wstawianie jest bardzo zbliżone do odnajdowania elementu:
– Odnajdujemy właściwe miejsce w drzewie, w które chcemy wstawić
nowy węzeł z.
Dodawany węzeł z zawsze staje się liściem.
Zakładamy, że początkowo left(z) oraz right(z) mają wartość null.
15
Wstawanie – przykład
Wstawiamy 13 do drzewa
12
5
18
2
9
z
15
13
19
17
16
Wstawianie – pseudokod
Tree-Insert(T,z)
y null
x root[T]
while x ≠ null
do y x
if key[z] < key[x]
then x left[x]
else x right[x]
parent[z] y
// dla pustego drzewa
if y = null then root[T] z
else if key[z] < key[y]
then left[y] z
else right[y] z
17
Usuwanie z drzewa BST
Usuwanie elementu jest bardziej skomplikowane niż wstawianie. Można
rozważać trzy przypadki usuwania węzła z:
1.
z nie ma potomków
2.
z ma jednego potomka
3.
z ma 2 potomków
przypadek 1: usuwamy z i zmieniamy u rodzica wskazanie na null.
przypadek 2: usuwamy z a jego dziecko staje się dzieckiem rodzica.
przypadek 3:najbardziej złożony; nie można po prostu usunąć węzła i
przenieść dzieci do rodzica – drzewo przestałoby być binarne!
18
Usuwanie z drzewa BST - przypadek 1
delete
usuwamy
19
Usuwanie z drzewa BST przypadek 2
Usuwany
węzeł
20
Usuwanie z drzewa BST
przypadek 3
Rozwiązanie polega na zastąpieniu węzła jego następnikiem.
założenie: jeśli węzeł ma dwóch potomków, jego następnik ma co
najwyżej jednego potomka.
dowód: jeśli węzeł ma 2 potomków to jego następnikiem jest minimum z
prawego poddrzewa. Minimum nie może posiadać lewego potomka
(inaczej nie byłoby to minimum)
21
Usuwanie z drzewa BST – przypadek 3
Usuwamy z
z
α
y
δ
β
y
α
δ
β
w
w
22
Usuwanie z drzewa BST – przypadek 3
usuwamy
następnik
23
Usuwanie z drzewa BST – pseudokod
Tree-Delete(T,z)
if left[z] = null or right[z] = null /* p. 1 lub 2
then y z
else y Tree-Successor(z)
if left[y] ≠ null
then x left[y]
else x right[y]
if x ≠ null
then parent[x]
parent[y]
if parent[y] = null
then root[T] x
else if y = left[parent[y]]
then left[parent[y]] x
else right[parent[y]] x
if y ≠ z
then key[z] key[y]
return y
24
Analiza złożoności
Usuwanie: dwa pierwsze przypadki wymagają O(1) operacji: tylko
zamiana wskaźników.
Przypadek 3 wymaga wywołania Tree-Successor, i dlatego wymaga
czasu O(h).
Stad wszystkie dynamiczne operacje na drzewie BST zajmują czas O(h),
gdzie h jest wysokością drzewa.
W najgorszym przypadku wysokość ta wynosi O(n)
25
Rotacje
Zachowują własność drzewa BST.
Zajmują stały czas O(1) – stała ilość operacji na wskaźnikach.
Rotacje w lewo i w prawo są symetryczne.
26
Rotacje
Rotacja w prawo
y
x
Rotacja w lewo
x
α
δ
β
α≤x≤β i x≤y≤δ
y
α
β
δ
α≤x≤y i β≤y≤δ
27
Left-Rotate
Inicjuj y
Left-Rotate(T,x)
y right[x]
right[x] left[y]
Zamień lewe poddrzewo y na prawe
poddrzewo x
parent[left[y]] x
parent[y] parent[x]
Przyłącz ojca x jako ojca y
if parent[x] = null
then root[T] y
else if x = left[parent[x]] then left[parent[x]] y
else right[parent[x]] y
left[y] x
Przyłącz x jako lewego syna y
parent[x] y
28
Przykład: Left-Rotate (1)
7
4
3
x
11
6
9
19
14
2
12
y
18
22
17
20
29
Przykład: Left-Rotate (2)
7
4
3
x
11
6
9
α
2
y
18
19
14
12
22
17
β
20
δ
30
Przykład: Left-Rotate (3)
7
4
3
2
y
18
x
11
6
19
14
9
22
α
12
17
β
20
δ
31
Przykład: Left-Rotate (4)
7
4
3
2
y
18
11
6
x
19
14
9
12
22
17
20
32

Podobne dokumenty