Zaawansowane algorytmy i struktury danych/Wykład 12: Różnice pomiędzy wersjami
Nie podano opisu zmian |
|||
Linia 106: | Linia 106: | ||
1 '''if''' <math>|Q|=2</math> '''then''' '''return''' <math>\infty</math> | 1 '''if''' <math>|Q|=2</math> '''then''' '''return''' <math>\infty</math> | ||
2 '''if''' <math>|Q|=2</math> '''then''' '''return''' <math>|Q[1] - Q[2]|</math> | 2 '''if''' <math>|Q|=2</math> '''then''' '''return''' <math>|Q[1] - Q[2]|</math> | ||
3 korzystając z tablicy <math>X</math> znajdź pionową prostą <math>l</math> taką, że po jej lewej i prawej stronie jest <math>\lfloor \frac{|Q|}{2} \rfloor</math> punktów | 3 korzystając z tablicy <math>X</math> znajdź pionową prostą <math>l</math> taką, że po jej lewej i | ||
prawej stronie jest <math>\lfloor \frac{|Q|}{2} \rfloor</math> punktów | |||
4 niech <math>Q_L</math> i <math>Q_P</math> to będą punkty odpowiednio po lewej i prawej stronie <math>l</math> | 4 niech <math>Q_L</math> i <math>Q_P</math> to będą punkty odpowiednio po lewej i prawej stronie <math>l</math> | ||
5 wyznacz tablice <math>X_L,X_P</math> oraz <math>Y_L,Y_P</math> | 5 wyznacz tablice <math>X_L,X_P</math> oraz <math>Y_L,Y_P</math> | ||
Linia 142: | Linia 143: | ||
Jeżeli najmniej odległa para punktów znajduje się w zbiorze <math>Q_L</math> bądź <math>Q_P</math> to zostanie ona znaleziona w wywołaniu rekurencyjnym. W takim razie musimy rozważyć tylko przypadek, w którym najmniej odległa para punktów to <math>p_L\in Q_L</math> i <math>p_R \in Q_R</math>. Oznaczmy, tak jak w algorytmie, przez <math>d</math> najmniejszą z odległości <math>d_L</math> i <math>d_R</math>. Widzimy teraz, że aby odległość między <math>p_L</math> i <math>p_R</math> mogła być mniejsza niż <math>d</math>, to punkty te nie mogą być bardziej odległe od <math>l</math> niż o <math>d</math>. W związku z tym usunięcie bardziej odległych punktów z <math>Y</math> w linii 9 algorytmu nie zmieni wyniku. | Jeżeli najmniej odległa para punktów znajduje się w zbiorze <math>Q_L</math> bądź <math>Q_P</math> to zostanie ona znaleziona w wywołaniu rekurencyjnym. W takim razie musimy rozważyć tylko przypadek, w którym najmniej odległa para punktów to <math>p_L\in Q_L</math> i <math>p_R \in Q_R</math>. Oznaczmy, tak jak w algorytmie, przez <math>d</math> najmniejszą z odległości <math>d_L</math> i <math>d_R</math>. Widzimy teraz, że aby odległość między <math>p_L</math> i <math>p_R</math> mogła być mniejsza niż <math>d</math>, to punkty te nie mogą być bardziej odległe od <math>l</math> niż o <math>d</math>. W związku z tym usunięcie bardziej odległych punktów z <math>Y</math> w linii 9 algorytmu nie zmieni wyniku. | ||
Rozważmy teraz prostokąt rozmiaru <math>2d \times d</math> ułożony centralnie na linii <math>l</math>, w kwadracie tym może znajdować się co najwyżej <math>8</math> punktów z <math>Q_L</math> i <math>Q_R</math> gdyż odległość między nimi jest co najmniej <math>d</math>. Zauważmy, że punktów mieszczących się w tym prostokącie znajdujących się poniżej danego punktu jest co najwyżej 7. Gdyby było ich więcej to odległość między nimi musiałaby być mniejsza niż <math>d</math>. Dlatego też w linii 11 algorytmu możemy ograniczyć się do przejrzenia tylko 7 kolejnych punktów. | Rozważmy teraz prostokąt rozmiaru <math>2d \times d</math> ułożony centralnie na linii <math>l</math>, w kwadracie tym może znajdować się co najwyżej <math>8</math> punktów z <math>Q_L</math> i <math>Q_R</math> gdyż odległość między nimi jest co najmniej <math>d</math>. Zauważmy, że punktów mieszczących się w tym prostokącie znajdujących się poniżej danego punktu jest co najwyżej 7 (zobacz rysunek poniżej). | ||
<flash>file=Zasd_Ilustr_g_stat.swf|width=400|height=200</flash> | |||
Gdyby było ich więcej to odległość między nimi musiałaby być mniejsza niż <math>d</math>. Dlatego też w linii 11 algorytmu możemy ograniczyć się do przejrzenia tylko 7 kolejnych punktów. | |||
}} | }} |
Wersja z 11:12, 3 sie 2006
Abstrakt
W ramach tego wykładu przedstawimy dwa algorytmu obrazujące wykorzystanie dwóch technik konstrukcji algorytmów geometrycznych. Do konstrukcji algorytmu sprawdzającego, czy w zbiorze odcinków istnieją dwa przecinające się użyjemy techniki zamiatania. Natomiast do konstrukcji algorytmu wyznaczającego najmniejszą odległość w zbiorze punktów użyjemy techniki dziel i zwyciężaj.
Przecinanie się zbioru odcinków
przecinanie_się_zbioru_odcinków Problem jaki nas będzie interesował, to problem przecinania się zbioru odcinków, w którym mamy za zadanie sprawdzić, czy w danym zbiorze odcinków istnieją dwa które się przecinają. Wykorzystamy tutaj algorytm sprawdzania, czy para odcinków się przecina zaprezentowany na poprzednim wykładzie (zobacz).
W celu uproszczenia prezentacji idei algorytmu poczynimy dwa upraszczające założenia. Po pierwsze załóżmy, że żaden z odcinków nie jest pionowy. Po drugie załóżmy, że żadne trzy odcinki nie przecinają się w jednym punkcie. Algorytm ten może być prosto zmieniony tak aby działał bez tych założeń.Ćwiczenie 1 do tego wykładu polega na pokazaniu tej modyfikacji. Jednak nie zawsze jest tak prosto. Bardzo często największym kłopotem w dowiedzeniu poprawności działania algorytmu geometrycznego jest poradzenie sobie ze wszystkimi szczególnymi i brzegowymi przypadkami.
Ponieważ założyliśmy, że w zbiorze nie ma odcinków pionowych, to każdy z odcinków może przecinać miotłę w co najwyżej jednym punkcie. Dlatego dla każdego położenia miotły możemy więc uporządkować odcinki przecinające ją zgodnie z kolejnością przecięć. Niech i będą dwoma odcinakami. Powiemy, że są one porównywalne w jeżeli miotła umieszczona w przecina je obydwa. Mówimy, że jest powyżej w , i oznaczamy , jeżeli i są porównywalne w oraz przecięcie z miotłą w jest wyżej niż przecięcie z z tą miotłą.
Ćwiczenie
Pokaż, używając technik z poprzedniego wykładu, jak sprawdzić, czy dwa odcinki i są porównywalne w ?
Ćwiczenie
Pokaż używając technik z poprzedniego wykładu jak sprawdzić, czy dla dwóch porównywalnych nie przecinających się odcinków i zachodzi ?
Dla każdego porządek jest porządkiem całkowitym na odcinkach przecinających miotłę w . Jednak porządek ten może być różny dla różnych ponieważ:
- dla różnych położeń miotły różne odcinki ją przecinają,
- jeżeli odcinki się przecinają to ich kolejność po obydwu stronach przecięcia jest różna.
Co więcej ponieważ zakładamy, że żadne trzy odcinki nie przecinają się w tym samym punkcie, to dla każdej pary przecinających się odcinków i musi istnieć takie położenie miotły dla którego i będą kolejne w porządku . Tą własność właśnie wykorzystamy w algorytmie który za chwile skonstruujemy.
Algorytm
Będziemy przechowywać informację o porządku na odcinkach aktualnie przecinających miotłę w strukturze pozwalającej na wykonanie następujących operacji:
- WSTAW - wstawia odcinek do porządku ,
- USUŃ - usuwa odcinek z porządku ,
- POPRZEDNI - zwraca odcinek przed w porządku ,
- NASTĘPNY - zwraca odcinek po w porządku .
Jeżeli zaimplementujemy tą strukturę z użyciem zrównoważonych drzew przeszukiwania, to operacje te będziemy mogli zrealizować w czasie , gdzie to całkowita liczba odcinków. Poniższy algorytm zwraca TRUE wtedy i tylko wtedy gdy zbiór przekazany my jako argument zawiera parę przecinających się odcinków.
Algorytm sprawdza, w zbiorze istnieją dwa przecinające się odcinki
ZBIÓR-ODCINKÓW-SIĘ-PRZECINA 1 2 niech będzie posortowanym zbiorem końcy odcinków z od lewej do prawej 3 for każdego do 4 begin 5 if to lewy koniec odcinka then 6 begin 7 WSTAW 8 POPRZEDNI 9 NASTĘPNY 10 if ODCINKI-SIĘ-PRZECINAJĄ then return TRUE 11 if ODCINKI-SIĘ-PRZECINAJĄ then return TRUE 12 end 13 if to prawy koniec odcinka then 14 begin 15 POPRZEDNI 16 NASTĘPNY 17 if Parser nie mógł rozpoznać (nieznana funkcja „\s”): {\displaystyle s_p \neq NIL \s_n \neq NIL \mbox{ i } } ODCINKI-SIĘ-PRZECINAJĄ then return TRUE 18 USUŃ 19 end 20 end 21 return FALSE
Następująca animacja przedstawia działania tego algorytmu.
<flash>file=Zasd_Ilustr_k_04.swf|width=600|height=300</flash>
Twierdzenie poprawność_odcinków
Dowód
Załóżmy, że w jest co najmniej jedno przecięcie. Niech będzie tym najbardziej na lewo spośród nich. Niech i będą odcinkami przecinającymi się w . Ponieważ po lewej stronie nie ma żadnych przecięć, to porządek przechowywany w jest poprawny do momentu przekroczenia . Jak zauważyliśmy poprzednio istnieje takie położenie miotły, dla którego i są kolejne w porządku . Co więcej istnieje takie , że miotła w jest na lewo od . Takie istnieje ponieważ założyliśmy, że trzy odcinki nie przecinają się w jednym punkcie. W takim bądź razie widzimy, że w porządek w poprawnie reprezentuje porządek . Odcinki i mogły się stać kolejne w :
Algorytm ten działa w czasie gdyż na jego czas działania składa się:
- wykonanie linii 2 w czasie ,
- wykonanie dla każdego końca odcinka pętli for w liniach 4-20 w całkowitym czasie - w każdym wykonaniu pętli wywoływanych jest stała liczba operacji na strukturze .
Najmniej odległa para punktów
Będziemy się teraz zajmować problemem znalezienia najmniej odległej pary punktów w zbiorze , gdzie . Interesować nas tutaj będzie odległość Euklidesowa, która dla punktów , oznaczamy przez , oraz definiujemy:
Dwa punkty w zbiorze mogą mieć tą samą współrzędną, w takim przypadku odległość między nimi wynosi . Informacja o najbliższej parze punktów może być przydatna w wypadku, gdy chcemy wykrywać kolizję między obiektami np. w systemach kontroli ruchu. Wyznaczając wszystkie odległości między parami punktów możemy ten problem rozwiązać w czasie . Pokażemy teraz jak wykorzystując technikę dziel i zwyciężaj problem ten można rozwiązać w czasie .
W celu uniknięcia wielokrotnego sortowania punktów w wywołaniach rekurencyjnych. Wykorzystamy dwie tablice i , które zawierały będą wszystkie punkty z posortowane odpowiednio po 'owej współrzędnej i 'owej współrzędnej. Jeżeli podzielimy zbiór na dwie części i , to odpowiednie tablice i zawierające posortowane elementy z i można wyznaczyć w czasie . Musimy po prostu przeglądając tablicę oraz kopiować elementy w napotkanej kolejności do mniejszych tablic.
Algorytm znajduje najmniejszą odległość między parą punktów w
NAJMNIEJ-ODLEGŁA-PARA 1 if then return 2 if then return 3 korzystając z tablicy znajdź pionową prostą taką, że po jej lewej i prawej stronie jest punktów 4 niech i to będą punkty odpowiednio po lewej i prawej stronie 5 wyznacz tablice oraz 6 Parser nie mógł rozpoznać (błąd składni): {\displaystyle d_L = NAJMNIEJ-ODLEGŁA-PARA(Q_L, X_L, Y_L)} 7 Parser nie mógł rozpoznać (błąd składni): {\displaystyle d_R = NAJMNIEJ-ODLEGŁA-PARA(Q_R, X_R, Y_R)} 8 9 niech będzie tablicą po usunięciu z niej punktów odległych od o więcej niż 10 for to do 11 for to do 12 if then 13 return
Działanie tej procedury przedstawione jest na poniższej animacji. <flash>file=Zasd_Ilustr_g_02.swf|width=600|height=300</flash>
Nie wliczając wywołań rekurencyjnych procedura ta działa w czasie liniowym. Zakładając, że , otrzymujemy równanie rekurencyjne na czas działania w postaci
Którego rozwiązaniem jest . Zauważmy, że czas potrzebny na posortowanie po raz pierwszy tablic i także wynosi . Całkowity czas potrzebny na znalezienie najmniejszej odległości między parą punktów w -elementowym zbiorze wynosi więc .
Twierdzenie poprawność_odległości
Dowód
Rozważmy teraz prostokąt rozmiaru ułożony centralnie na linii , w kwadracie tym może znajdować się co najwyżej punktów z i gdyż odległość między nimi jest co najmniej . Zauważmy, że punktów mieszczących się w tym prostokącie znajdujących się poniżej danego punktu jest co najwyżej 7 (zobacz rysunek poniżej).
<flash>file=Zasd_Ilustr_g_stat.swf