KD-drzewa
Geometria Obliczeniowa - projekt
Bartłomiej Szczepanik
agenda
- Problemy wyszukiwania
- Rozwiązanie w 1D
- Drzewo czwórkowe - dwie wersje
- KD-drzewo
- budowa
- wyszukiwanie punktów w przedziale
- wyszukiwanie najblizszego sąsiada
- dodawanie, usuwanie, balancing
- Demo
problemy wyszukiwania
- Find - czy punkt znajduje się w zbiorze
-
Nearest Neighbour - najblizszy punkt
od podanego w zbiorze -
Range Query - wyszukiwanie punktów
w zadanym przedziale
(niekoniecznie prostokątnym) -
Ray Shooting - mając dany promień,
jaki obiekt pierwszy zostanie
trafiony przez ten promień
Zastosowania
- wyszukiwanie kolizji
- zapytania w bazie danych
- raytracing
- wyswietlanie sceny 3D
- regresja/machine learning
Jeden wymiar
Sortowanie + wyszukiwanie binarne
JEDEN WYMIAR
(statyczne) drzewo przedziałowe
Jeden wymiar
Jak to uogólnić?
drzewa czwórkowe
Drzewa czwórkowe
drzewa czwórkowe
Wady:
- słaba skalowalnosc na
większą liczbę wymiarów (3 max) - większa zajętosc pamięci
- wiele niepotrzebnych przedziałów
- nie adaptuje się do dystrybucji punktów
Drzewa czwórkowe
Wersja punktowa
kd-drzewo - idea
Drzewo przedziałowe
dzielące cyklicznie po kolejnych wymiarach
kd-drzewo - Budowa
def buildTree(points, axis):
if len(points) == 1:
return Node(points[0])
median = math.median(points, itemgetter(axis))
left, right = splitBy(points, median, axis)
node = Node(median)
node.left = buildTree(leftPoints, (axis + 1) % 2)
node.right = buildTree(rightPoints, (axis + 1) %2)
return node;
kd-drzewo - budowa
Koszt:
Wyszukiwanie mediany: O(n)
Całosc:
T(n) = 2T(n/2) + O(n)
T(n) = O(n log n)
wyszukiwanie przedzialu
def processChild(child, range):
if range.fullyContains(child.range):
return root.getWholeSubtreeAsList()
elif range.intersects(child.range):
return search(child, range)
def search(root, range):
if root.leaf:
return [root.point] if range.contains(root.point)
else []
return processChild(root.left, range) +
processChild(root.right, range)
wyszukiwanie przedzialu
Koszt
T(n) = 2T(n/4)
T(n) = n^(1/2)
W ogólnosci (d -wymiarowe drzewo):
T(n) = 2^(d-1) T(n / 2^d)
T(n) = n^(1-1/d)
Problem czuły na rozwiązanie:
T(n,k) = n^(1/2) + k
Sprawdzanie przynaleznosci
punktu do zbioru
Sprowadza się do
pytania o przedział [x,y]-[x,y]
pytania o przedział [x,y]-[x,y]
T(n) = log n
Wyszukiwanie najblizszego
sasiada
T(n) = log n
wstawianie, usuwanie
Balancing
Wstawianie, usuwanie - identycznie jak w BST
Balancing - tricky!
kd-drzewo - wady
- da się szybciej
- curse of dimensionality
DEMO
Podsumowanie
Pytania?
Podsumowanie
Dziękuje za uwagę!
KDdrzewa
By mequrel
KDdrzewa
- 1,912