Professional Documents
Culture Documents
GGAW3
GGAW3
49
23 80
10 37 62 89
3 19 30 49 59 70 89 93
3 10 19 23 30 37 59 62 70 80 93 97
10 37 62 89
3 19 30 49 59 70 89 93
3 10 19 23 30 37 59 62 70 80 93 97
l1 przedział [18, 77] l2
l1 l2
Lemat 3.1. Powyższy algorytm wylicza dokładnie te i tylko te punkty z S, które
leżą w obszarze zapytania [x1, x2].
T
Należy wykazać, że każdy ze zgłaszanych
punktów leży w obszarze [x1, x2]. vdziel
l1 l2
Twierdzenie 3.2. (???)
Niech S będzie zbiorem n punktów na prostej rzeczywistej R. Zbiór S można zapa-
miętać w zrównoważonym drzewie poszukiwań binarnych, które korzysta z pamięci
rzędu O(n) i ma czas konstrukcji O(n log n), tak że punkty w obszarze zapytania
można podać w czasie O(k + log n), gdzie k jest liczbą podawanych punktów.
Liczba węzłów wewnętrznych każdego drzewa binarnego jest mniejsza od liczby
liści, a zatem wyliczenie wszystkich liści danego poddrzewa wymaga czasu
liniowego względem liczby k podawanych punktów.
Jako że drzewo jest zrównoważone, liczba odwiedzanych węzłów przy poszuki-
waniu x1 i x2 wynosi O(log n).
3.2 Zapytania w przestrzeni dwywymiarowej: kd-drzewa
a) b)
l5 l1 l7
l1
p9
p10 l2 l3
p4
p5
l2 l4 l5 l6 l7
p2 l3
p7 p8
l8 l8 p3 p4 p5 l9 p8 p9 p10
p1 p6
l9
p3 p1 p2 p6 p7
l4 l6
(a) Podział płaszczyzny i (b) odpowiadające mu kd-drzewo.
l1
p9
p10 l2 l3
p4
p5
l4 l5 l6 l7
p2
p7 p8
l8 p3 p4 p5 l9 p8 p9 p10
p1 p6
p3 p1 p2 p6 p7
Lemat 3.3. Dla zbioru n-punktów na płaszczyźnie można w czasie O(n log n) skon-
struować dwuwymiarowe kd-drzewo, które korzysta z pamięci rzędu O(n).
Pamięć O(n) − bo drzewo binarne, w którym każdy liść pamięta inny punkt.
Idea algorytmu zapytań
l1
l1
l2
l3
l2 v
obszar(v)
l3
p12 l2 l3
p4
p2 p5 p13
l2 l4 l4 l5 l6
p8
l3 l4 p3 p4 p5 l7 p11 p12 p13
p10
p1 p7
p9 p11 p1 p2 p6 ∗
l7 p6 p6
p6
p3 R
p7 p8 p9 p10
l4 l5
Wszystkie zielone węzły są odwiedzane, natomiast zgłaszane są jedynie liście p6, p11 oraz te ciemnozielone.
/Uwaga − Przykładowe drzewo nie jest zrównoważonym kd-drzewem./
◮ A zatem przechodzimy kd-drzewo odwiedzając tylko te węzły v, których ob-
szar obszar(v) przecinany jest przez obszar zapytania R, a ponadto:
gdy obszar obszar(v) jest całkowicie zawarty w prostokącie zapytania, mu-
simy podać wszystkie punkty pamiętane w tym poddrzewie;
gdy dotrzemy do liścia (w inny niż w/w sposób), musimy sprawdzić, czy
punkt pamiętany w tym liściu należy do obszaru R i, jeśli tak, zgłosić go.
p12 l2 l3
p4
p2 p5 p13
l2 l4 l4 l5 l6
p8
l3 l4 p3 p4 p5 l7 p11 p12 p13
p10
p1 p7
p9 p11 p1 p2 p6 ∗
l7 p6 p6
p6
p3 R
p7 p8 p9 p10
l4 l5
Szacujemy liczbę ciemnozielonych węzłów.
Przypadek 2: obszar(v) 6⊆ prostokąt zapytania R.
l1 l6
l1
p12 l2 l3
p4
p2 p5 p13
l2 l4 l4 l5 l6
p8
l3 l4 p3 p4 p5 l7 p11 p12 p13
p10
p1 p7
p9 p11 p1 p2 p6 ∗
l7 p6 p6
p6
p3 R
p7 p8 p9 p10
l4 l5
Szacujemy liczbę jasnozielonych lub niebieskich węzłów.
Przypadek 2: obszar(v) 6⊆ prostokąt zapytania R.
l1 l6
l1
p12 l2 l3
p4
p2 p5 p13
l2 l4 l4 l5 l6
p8
l3 l4 p3 p4 p5 l7 p11 p12 p13
p10
p1 p7
p9 p11 p1 p2 p6 ∗
l7 p6 p6
p6
p3 R
p7 p8 p9 p10
l4 l5
p1 p7 p10
p9 p11 p1 p2 p6 ∗
l7 p6 p6
p6
p3 R
p7 p8 p9 p10
l4 l5
Niech l będzie dowolną pionową prostą i niech Q(n) będzie liczbą przecinanych ob-
szarów przez l w kd-drzewie przechowującym n-punktów na płaszczyźnie, którego
korzeń zawiera pionową prostą dzielącą.
jeśli n = 1;
O(1)
Q(n) =
2 + 2 · Q(⌈n/4⌉) w przeciwnym wypadku.
√
Rozwiązaniem tego równania jest Q(n) = O( n).
l
prosta l przecina obszar(korzeń)
l1 l6 Q(n)
l1 prosta l przecina
obszar(prawy-syn(korzeń))
p12 l2 l3
p4
Q(⌈ n4 ⌉)
p2 p5 p13
l2 l4 l4 l5 l6 Q(⌈ n4 ⌉)
p8
l3 l4 p3 p4 p5 l7 p11 p12 p13
p1 p7 p10
p9 p11 p1 p2 p6 ∗
l7 p6 p6
p6
p3 R
p7 p8 p9 p10
l4 l5
Niech l będzie dowolną pionową prostą i niech Q(n) będzie liczbą przecinanych ob-
szarów przez l w kd-drzewie przechowującym n-punktów na płaszczyźnie, którego
korzeń zawiera pionową prostą dzielącą.
jeśli n = 1;
O(1)
Q(n) =
2 + 2 · Q(⌈n/4⌉) w przeciwnym wypadku.
√
Rozwiązaniem tego równania jest Q(n) = O( n).
⊲ W analogiczny sposób można udowodnić, że liczba √ obszarów przecinanych
przez dowolną prostą poziomą jest także rzędu O( n).
A zatem całkowita liczba
√ obszarów przecinanych przez brzeg prostokąta zapytania
jest również rzędu O( n).
Twierdzenie 3.5. (Bentley 1975) Kd-drzewo dla n-elementowego zbioru S ⊂ R2
punktów wymaga O(n) pamięci i można je zbudować w czasie O(n log √n). Zapytanie
o prostokątny obszar zapytania dla kd-drzewa wymaga czasu rzędu O( n+k), gdzie
k jest liczbą zgłaszanych punktów.
Twierdzenie 3.5. (Bentley 1975) Kd-drzewo dla n-elementowego zbioru S ⊂ R2
punktów wymaga O(n) pamięci i można je zbudować w czasie O(n log √n). Zapytanie
o prostokątny obszar zapytania dla kd-drzewa wymaga czasu rzędu O( n+k), gdzie
k jest liczbą zgłaszanych punktów.
Wielowymiarowe kd-drzewa
◮ W korzeniu zbiór punktów dzielony jest względem pierwszej współrzędnej tych
punktów. W dzieciach korzenia podział ten dokonywany jest względem drugiej
współrzędnej. W węzłach o głębokości dwa − względem trzeciej współrzędnej.
◮ . . . aż do głębokości d − 1, na której dzielimy względem ostatniej współrzędnej.
◮ Na głębokości d − podział znowu względem pierwszej współrzędnej, itd.
◮ Rekursja zatrzymuje się, gdy pozostał tylko jeden punkt, który zapamiętywany
jest w liściu.
◮ Ponieważ d-wymiarowe kd-drzewo dla zbioru n-punktów jest drzewem binar-
nym o n liściach, więc korzysta ono z pamięci rzędu O(n).
◮ Czas konstrukcji wynosi O(n log n). (Zakładamy, że d jest stałą.)
◮ Można pokazać, że czas zapytania jest rzędu O(n1−1/d + k).
3.3 Dwuwymiarowe drzewa obszarów
drzewo wyszukiwań
T
binarnych względem
współrzędnej x
S(v) S(v)
y1
x1 ≤ O(log n) pasków ≤ x2
◮ Jeśli dla dowolnego S(vi) dostępne jest drzewo wyszukiwań binarnych wzglę-
dem współrzędnej y, wówczas, wykonując jednowymiarowe zapytanie na tym
drzewie, jesteśmy w stanie znaleźć w czasie O(log |S(vi)| + kvi ) wszystkie kvi
punktów z S(vi), których współrzędna y mieści się w przedziale [y1, y2].
Dwupoziomowa struktura danych zwana drzewem obszarów.
◮ Główne drzewo jest zrównoważonym drzewem przeszukiwan binarnych T zbu-
dowanym względem współrzędnej x punktów z S.
Dla każdego węzła wewnętrznego lub liścia v w drzewie T , podzbiór kano-
niczny S(v) jest pamiętany w zrównoważonym drzewie przeszukiwań binarnych
Tstow(v) względem współrzędnej y punktów (tzw. struktura stowarzyszona z v);
węzeł v pamięta wskaźnik do drzewa Tstow(v).
drzewo wyszukiwań
T
binarnych względem
współrzędnej x
S(v)
drzewo wyszukiwań
binarnych dla S(v)
S(v) względem współrzędnej y
drzewo wyszukiwań
binarnych dla S(v)
S(v) względem współrzędnej y
jeśli n = 1;
O(1)
T (n) =
2 · T (n/2) + O(n) w przeciwnym wypadku,
którego rozwiązaniem jest T (n) = O(n log n). A zatem czas konstrukcji drzewa,
mając na uwadze wykonane wcześniej przetwarzanie wstępne, wynosi O(n log n).
Złożoność pamięciowa algorytmu
Lemat 3.7. Drzewo obszarów dla zbioru n punktów na płaszczyźnie wymaga pa-
mięci rzędu O(n log n).
Lemat 3.7. Drzewo obszarów dla zbioru n punktów na płaszczyźnie wymaga pa-
mięci rzędu O(n log n).
Lemat 3.7. Drzewo obszarów dla zbioru n punktów na płaszczyźnie wymaga pa-
mięci rzędu O(n log n).
Lemat 3.7. Drzewo obszarów dla zbioru n punktów na płaszczyźnie wymaga pa-
mięci rzędu O(n log n).
Otrzymujemy w konsekwencji:
Twierdzenie 3.8. (m.in. Bentley 1979; Lueker 1978)
Niech S będzie zbiorem n punktów na płaszczyźnie R2. Drzewo obszarów dla S
używa O(n log n) pamięci i można je zbudować w czasie O(n log n). Punkty S
leżące w prostokątnym obszarze zapytania można wyznaczyć w czasie O(log2 n+k),
gdzie k jest liczbą zgłaszanych punktów.
3.4 Wielowymiarowe drzewa obszarów
(−∞, x2 ] × [y1 , y2 ]
3.5 Drzewa przeszukiwań priorytetowych
Zastosowanie przy zapytaniach o dwuwymiarowy obszar ortogonalny R, z którego
jeden brzeg jest nieograniczony, tj. gdy R = (−∞, x2) × [y1, y2].
Kopiec jednowymiarowy
1
3 8
11 4 15 21
36 32
3 8
11 4 15 21
36 32
3 8
11 4 15 21
36 32
p5
p1
p2
p2
p1
p5
p4 p4
p6
p3
p3
p6
Ilustracja idei.
◮ Punkt p5 ma najmniejszą współrzędną x − zatem stanowi on korzeń drzewa.
◮ Pozostałe punkty dzielone są „na pół” względem współrzędnej y.
Punkty p3, p4 i p6 mają mniejszą współrzędną y od punktów p1 i p2. Pamię-
tane są w dolnym (lewym) poddrzewie, którego korzeniem jest p3 − punkt
ten ma najmniejszą współrzędną x spośród punktów p3, p4 i p6.
Punkty p1 i p2 pamiętane są w górnym (prawym) poddrzewie, którego ko-
rzeniem jest p1 (x(p1) < x(p2)).
p5
p1
p2
p2
p1
p5
p4 p4
p6
p3
p3
p6
do obszaru zapytania.
Dla każdego poddrzewa T pomiędzy
ścieżkami π1 i π2 wywołujemy poniższą y1
procedurę ReportInSubtree.
Rzędne punktów przechowywanych w T
należą do przedziału [y1, y2], zatem wy- y2
do obszaru zapytania.
Dla każdego poddrzewa T pomiędzy
ścieżkami π1 i π2 wywołujemy poniższą y1
procedurę ReportInSubtree.
Rzędne punktów przechowywanych w T
należą do przedziału [y1, y2], zatem wy- y2
do obszaru zapytania.
Dla każdego poddrzewa T pomiędzy
ścieżkami π1 i π2 wywołujemy poniższą y1
procedurę ReportInSubtree.
Rzędne punktów przechowywanych w T
y2
należą do przedziałux [y1 , y2 ], zatem wy-
ReportInSubtree(v, 2)
starczy sprawdzić tylko odciętą tych
Wejście. Korzeń poddrzewa przeszukiwań priotytetowych i wartość x2.
punktów.
Wyjście. Wszystkie punkty w poddrzewie o odciętej nie większej od x2.
1. if v 6= null oraz x(p(v)) ≤ x2
2. then Podaj p(v).
3. then ReportInSubtree(lewy-syn(v), x2)
4. then ReportInSubtree(prawy-syn(v), x2)
Lemat 3.10. Procedura ReportInSubtree(v, x2) podaje w czasie rzędu
O(1 + kv ) wszystkie punkty w poddrzewie zakorzenionym w węźle v, których od-
cięta jest nie większa od x2, gdzie kv jest liczbą podawanych punktów.
x(rodzic(w)) ≤ x2
vdziel
y1
y2
◮ Należy wykazać, że każdy punkt zgłaszany przez algorytm leży w obszarze za-
pytania.
Węzły leżące na ścieżkach π1 i π2 poszukiwań y1 oraz y2 są sprawdzane
bezpośrednio, czy leżą w obszarze zapytania.
Węzły leżące w poddrzewach pomiędzy ścieżkami π1 i π2 . . .
vdziel
y1
y2
y1
y2
y1
y2
y1
y2
ReportSubtree jest procedurą, która przechodzi poddrzewo zakorzenione w danym węźle i wylicza wszystkie
punkty pamiętane w jego liściach.
FindSplitNode(T , x1, x2)
Wejście. Drzewo T i dwie wartości x1, x2 ∈ R, x1 ≤ x2.
Wyjście. Węzeł vdziel , w którym rozchodzą się ścieżki w poszukiwaniu x1 i x2;
Wyjście. lub liść, w którym obie ścieżki kończą się.
1. v := korzeń(T );
2. while v nie jest liściem oraz (x2 ≤ klucz(v) lub x1 > klucz(v)) do
2.1 if x2 ≤ klucz(v) then v := lewy-syn(v);
2.2 else v := prawy-syn(v);
3. Zwróć v.
1DRangeQuery(T , [x1, x2])
Wejście. Drzewo T i przedział [x1, x2].
Wyjście. Wszystkie punkty z T , które leżą w przedziale [x1, x2].
1. vdziel := FindSplitNode(T , x1, x2);
2. if vdziel jest liściem
3. then Sprawdź, czy klucz(vdziel) musi być podany (∈ [x1, x2]).
4. else /* Idź ścieżką do l1 i wyliczaj punkty w poddrzewach na prawo od ścieżki.*/
5. v := lewy-syn(vdziel);
6. while v nie jest liściem do
7. if x1 ≤ klucz(v)
8. then ReportSubtree(prawy-syn(v));
9. then v := lewy-syn(v);
10. else v := prawy-syn(v);
11. Sprawdź, czy punkt pamiętany w liściu v (= l1) musi być podany.
12. Analogiczne postępowanie dla ścieżki poszukiwań x2:
− wylicz punkty w poddrzewach na lewo od ścieżki;
− sprawdź, czy wartość na końcu ścieżki (liść) musi być podana.
2DRangeQuery(T , [x1, x2] × [y1 , y2])
Wejście. Dwuwymiarowe drzewo obszarów T i obszar [x1, x2] × [y1 , y2].
Wyjście. Wszystkie punkty z T , które leżą w obszarze zapytania.
1. vdziel := FindSplitNode(T , x1, x2);
2. if vdziel jest liściem
3. then Sprawdź, czy punkt pamietany w vdziel musi być podany.
4. else /* Idź ścieżką w poszukiwaniu x1 i wywołuj 1DRangeQuery
dla poddrzew stowarzyszonych na prawo od ścieżki.*/
5. v := lewy-syn(vdziel);
6. while v nie jest liściem do
7. if x1 ≤ klucz(v)
8. then 1DRangeQuery(Tstow (prawy-syn(v)), [y1, y2]);
9. then v := lewy-syn(v);
10. else v := prawy-syn(v);
11. Sprawdź, czy punkt pamiętany w liściu v musi być podany.
12. Analogiczne postępowanie dla ścieżki poszukiwań x2.
/* Idź ścieżką w poszukiwaniu x2 i wywołuj 1DRangeQuery dla poddrzew stowarzyszonych
na lewo od ścieżki i sprawdź, czy punkt pamiętany na końcu ścieżki musi być podany. */
QuerySearchTree(T , (−∞, x2] × [y1, y2])
Wejście. Korzeń drzewa przeszukiwań priotytetowych i obszar zapytania.
Wyjście. Wszystkie punkty w obszarze zapytania.
1. Wyszukaj y1 oraz y2 w kopcu T . Niech vdziel będzie węzłem, w którym ścieżki poszukiwań y1 oraz y2 rozchodzą
się, i niech v1 oraz v2 będą węzłami, w których skończyło się przeszukiwanie odpowiednio y1 oraz y2 . (Jeśli w
drzewie brak jest którejś z wartości, to odpowiedni wierzchołek końcowy ścieżki jest liściem).
2. for każdy węzeł v na ścieżce poszukiwań y1 oraz y2 do
3. if p(v) ∈ (−∞, x2] × [y1, y2]) then podaj p(v)
4. for każdy węzeł v na ścieżce z vdziel do v1 do
5. if w węźle v ścieżka poszukiwania y1 idzie w lewo
6. then ReportInSubtree(prawy-syn(v), x2)
7. for każdy węzeł v na ścieżce z vdziel do v2 do
8. if w węźle v ścieżka poszukiwania y2 idzie w prawo
9. then ReportInSubtree(lewy-syn(v), x2)