Wykład 6 Drzewa poszukiwań binarnych (BST)

Transkrypt

Wykład 6 Drzewa poszukiwań binarnych (BST)
Wykład 6
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])
czas wykonania:
T(0) = Θ(1)
T(n)=T(k) + T(n – k –1) + Θ(1)
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

Podobne dokumenty