2.6 Korrigierte Algorithmen

Werbung
2 KONVEXE HÜLLE
2.6
Korrigierte Algorithmen
Algorithmus 2.2’ (Konvexe Hülle Langsam korrigiert)
Eingabe: Endliche Menge P von Punkten der Ebene
Ausgabe: Liste L der Ecken von conv P in positiver Orientierung
1: E ← ∅
2: Für alle Paare (p, q) ∈ P × P mit p 6= q mache
3:
gültig ← wahr
4:
Für alle Punkte r ∈ P \ {p, q} mache
→
5:
Wenn r liegt streng rechts der gerichteten Strecke −
pq oder auf der Gerade pq
aber nicht innerhalb von pq dann
6:
gültig ← falsch
7:
Wenn gültig dann füge (p, q) zu E hinzu
8: Berechne L von E durch Verfolgung.
Algorithmus 2.4’ (Konvexe Hülle korrigiert)
Eingabe: Endliche Menge P von Punkten der Ebene
Ausgabe: Liste L der Ecken von conv P in positiver Orientierung
1: Sortiere die Punkte in P lexikographisch (nach x-Koordinate, bei Gleichheit nach
y-Koordinate), was eine Liste p1 , . . . , pn liefert.
2: Packe p1 , p2 in die Liste Lunten (p2 nach p1 )
3: Für alle i ← 3 bis n mache
4:
Füge pi an Lunten an
5:
Solange Lunten mehr als 2 Punkte enthält und die letzten 3 Punkte von Lunten
keine Linksdrehung ausführen, mache
6:
Lösche den vorletzen Punkt aus Lunten .
7: Packe pn , pn−1 in die Liste Loben
8: Für alle i ← n − 2 absteigend bis 1 mache
9:
Füge pi an Loben an
10:
Solange Loben mehr als 2 Punkte enthält und die letzten 3 Punkte von Loben
keine Linksdrehung ausführen, mache
11:
Lösche den vorletzen Punkt aus Loben .
12: Lösche den ersten und letzten Punkt von Loben .
13: Füge ganz Loben an Lunten , das Ergebnis ist L.
Algorithmische Geometrie, WS 2009/10
8
TUM, M9, Dr. Nico Düvelmeyer
3 SCHNITTPUNKTE VON STRECKEN
3
Schnittpunkte von Strecken
→
Bemerkung 3.1 (Einschub Balancierter Baum) Zitat von
http: // de. wikipedia. org/ wiki/ Suchbaum :
Der normale binäre Suchbaum ist zwar einfach zu implementieren, kann jedoch nicht garantieren, dass die oben genannten Operationen insert, delete
und find effizient ausgeführt werden können. Dazu gibt es spezielle binäre
Suchbäume, welche durch verschiedene Techniken garantieren, dass sie immer balanciert sind, und die Operationen insert, delete und find somit immer
effizient (in logarithmischer Zeit) ausgeführt werden können. Einige dieser
speziellen Suchbäume sind:
• 2-3-4-Baum
• AVL-Baum
• B-Baum
• Rot-Schwarz-Baum
• Kd-Baum
Auftrag 3.2
Gegeben: n Strecken der Ebene
Gesucht: Menge aller Schnittpunkte der abgeschlossenen Strecken, unter Angabe der beteiligten Strecken
Die Laufzeit soll ausgabeabhängig möglichst gut sein. Wir vermeiden also so gut wie
möglich die Schnittbestimmung von Strecken, die sich nicht schneiden.
3.1
3.1.1
Gleitebenenverfahren
Anfangsidee
Wir scheiden nur Strecken, deren y-Bereiche sich auch schneiden.
Status: Menge der Strecken, die die Gleitgerade schneiden.
Ereignispunkte: Anfangs- und Endpunkte der Strecken
Algorithmische Geometrie, WS 2009/10
9
TUM, M9, Dr. Nico Düvelmeyer
3 SCHNITTPUNKTE VON STRECKEN
3.1.2
Verfeinerung
Status: Sortierte Liste T der Strecken, wie sie die Gleitgerade (von links nach rechts)
schneiden. Balancierter Suchbaum.
Ereignispunkte: Anfangs-, End- und Schnittpunkte der Strecken, sortiert nach Abarbeitung: Von oben nach unten, bei Gleichheit von links nach rechts. Zu jedem Punkt
ist eine Menge dort beginnender Strecken gespeichert. Balancierter Suchbaum. Kein
Heap, da bereits enthaltene Punkte nicht nochmals eingefügt werden sollen. Ereigniswarteschlange Q.
Algorithmus 3.3
Eingabe: Menge S von Strecken der Ebene
Ausgabe: Eine Menge von Schnittpunkten mit Angabe der beteiligten Strecken
1: Funktion SucheSchnittpunkte(S)
2:
Initialisiere eine leere Ereigniswarteschlange Q. Füge die Randpunkte der Strecken
von S in Q ein. Zu den oberen Randpunkten wird auch die zugehörige Strecke gespeichert. Für horizontale Strecken betrachten wir den linken Randpunkt als oberes Ende
(Anfangspunkt).
3:
Initialisiere einen leeren Statusbaum T .
4:
Solange Q nicht leer ist, mache
5:
Bestimme den nächsten Ereignispunkt p aus Q und lösche diesen.
6:
BehandelEreignispunkt(p)
7: Unterprogramm BehandelEreignispunkt(p)
8:
Bezeichne mit U (p) die Menge der Strecken (aus Q), die in p beginnen.
9:
Suche alle Strecken in T , die p enthalten. L(p) sei die Menge jener Strecken, für
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
die p das untere Ende ist, und C(p) die Menge der Strecken von T mit p im Inneren.
Wenn L(p) ∪ U (p) ∪ C(p) mehr als eine Strecke enthält, dann
Melde p als Schnittpunkt, zusammen mit L(p), U (p) und C(p).
Lösche die Strecken in L(p) ∪ C(p) aus T .
Füge die Strecken in U (p) ∪ C(p) neu in richtiger Reihenfolge in T ein (horizontale
Strecken zum Schluss).
⊲ Löschen und Neueinfügen der Strecken von C(p)
vertauscht deren Reihenfolge
Wenn U (p) ∪ C(p) = ∅ dann
Bestimme linken Nachbarn sl und rechten Nachbarn sr von p in T .
SucheNeuesEreignis(sl ,sr ,p)
sonst
Sei s′ die Strecke am weitesten links von U (p) ∪ C(p) in T ,
und sl deren linker Nachbar in T .
SucheNeuesEreignis(sl ,s′ ,p) falls sl existiert.
Sei s′′ die Strecke am weitesten rechts von U (p) ∪ C(p) in T ,
und sr deren rechter Nachbar in T .
SucheNeuesEreignis(s′′ ,sr ,p) falls sr existiert.
24: Unterprogramm SucheNeuesEreignis(sl , sr , p)
25:
Wenn sl und sr sich unterhalb der Gleitebene schneiden (inklusive: direkt rechts
26:
von p auf dieser), und wenn deren Schnittpunkt noch nicht in Q enthalten ist, dann
Füge den Schnittpunkt in Q ein.
Algorithmische Geometrie, WS 2009/10
10
TUM, M9, Dr. Nico Düvelmeyer
3 SCHNITTPUNKTE VON STRECKEN
Satz 3.4 Alle Schnittpunkte und zugehörige Strecken werden korrekt von Algorithmus 3.3
bestimmt.
Beweis Mit Induktion folgt, dass jeder Schnittpunkt auch erkannt wird sobald zwei der
beteiligten Strecken benachbart werden. Dies passiert nur an Ereignispunkten. Bei der
Behandlung jedes Schnittpunktes p enthält T tatsächlich alle Strecken, die von der Waagerechten geschnitten werden, bis auf Strecken aus U (p).
¤
Satz 3.5 Die Laufzeit von Algorithmus 3.3 für n Strecken mit I Schnittpunkten ist in
O((n + I) log n).
Beweis Wir betrachten die einzelnen Anweisungen von Algorithmus 3.3.
1: Funktion SucheSchnittpunkte(S)
2:
Initialisiere eine leere Ereigniswarteschlange Q.
⊲ Zeit O(1)
Füge die Randpunkte der Strecken von S in Q ein. Zu den oberen Randpunkten wird
auch die zugehörige Strecke gespeichert. Für horizontale Strecken betrachten wir den
linken Randpunkt als oberes Ende (Anfangspunkt).
⊲ 2n mal Grundoperation
Suchen. Maximal 2n mal Grundoperation Einfügen in Q oder alternativ Einfügen in
Streckenmenge. Dabei Größe von Q maximal 2n. Zeit: O(n log n).
3:
Initialisiere einen leeren Statusbaum T .
⊲ Zeit O(1)
4:
Solange Q nicht leer ist, mache
5:
Bestimme den nächsten Ereignispunkt p aus Q und lösche diesen.
⊲
Maximal 2n + I Durchläufe, Grundoperationen in Q, von Größe maximal 2n + I. Zeit:
2(2n + I) log(2n + I) ∈ O((n + I) log n)
6:
BehandelEreignispunkt(p)
Beachte: I < n2 , log(2n + I) < log(2n2 ) = log 2 + 2 log n ∈ O(log n).
Jeder Durchlauf des innersten Algorithmus SucheNeuesEreignis(sl , sr , p), benötigt
Zeit in O(log |Q|), das ist in O(log n).
Unterprogramm BehandelEreignispunkt(p) wird maximal 2n + I mal ausgeführt.
7: Unterprogramm BehandelEreignispunkt(p)
8:
Bezeichne mit U (p) die Menge der Strecken (aus Q), die in p beginnen. ⊲ Zeit:
O(|U (p)|)
9:
Suche alle Strecken in T , die p enthalten. L(p) sei die Menge jener Strecken, für
die p das untere Ende ist, und C(p) die Menge der Strecken von T mit p im Inneren.
⊲ Zeit: O(log |T | + |L(p) ∪ C(p)|)
10:
Wenn L(p) ∪ U (p) ∪ C(p) mehr als eine Strecke enthält, dann
11:
Melde p als Schnittpunkt, zusammen mit L(p), U (p) und C(p).
⊲ Zeit
O(|L(p) ∪ C(p) ∪ U (p)|)
12:
Lösche die Strecken in L(p) ∪ C(p) aus T .
⊲ Zeit: O(|L(p) ∪ C(p)| log |T |)
13:
Füge die Strecken in U (p) ∪ C(p) neu in richtiger Reihenfolge in T ein (horizontale
Strecken zum Schluss).
⊲ Zeit O(|U (p) ∪ C(p)| log |T |)
14:
Wenn U (p) ∪ C(p) = ∅ dann
15:
Bestimme linken Nachbarn sl und rechten Nachbarn sr von p in T . ⊲ O(|T |)
16:
SucheNeuesEreignis(sl ,sr ,p)
⊲ Zeit: O(log n)
17:
sonst
18:
Sei s′ die Strecke am weitesten links von U (p) ∪ C(p) in T , ⊲ Zeit: O(log |T |)
Algorithmische Geometrie, WS 2009/10
11
TUM, M9, Dr. Nico Düvelmeyer
3 SCHNITTPUNKTE VON STRECKEN
und sl deren linker Nachbar in T .
⊲ Zeit: O(log |T |)
′
SucheNeuesEreignis(sl ,s ,p) falls sl existiert.
⊲ Zeit: O(log n)
Sei s′′ die Strecke am weitesten rechts von U (p) ∪ C(p) in T , ⊲ Zeit: O(log |T |)
und sr deren rechter Nachbar in T .
⊲ Zeit: O(log |T |)
SucheNeuesEreignis(s′′ ,sr ,p) falls sr existiert.
⊲ Zeit: O(log n)
19:
20:
21:
22:
23:
Mit m(p) := |L(p) ∪ U (p) ∪ C(p)| ist also der Zeitaufwand von BehandelEreignispunkt(p) in O(m(p) log n). Ist m die Summe aller m(p), so ist die Laufzeit aller Aufrufe
zusammen in O(m log n). Ist k die Größe der Ausgabe (Anzahl ausgegebener Punkte plus
jeweils der Anzahl der ausgegebenen zugehörigen Strecken), so folgt leicht m ∈ O(n + k).
Aber es gilt auch m ∈ O(n + I), was aus der Betrachtung des ebenen Graphen folgt: Die
ne Knoten werden von allen Schnitt- und Endpunkte gebildet, ne ≤ 2n+I. Die nk Kanten
des ebenen Graphen sind dann die ungeteilten Abschnitte der gegebenen Strecken. Die
Eulersche Polyederformel für alle Zusammenhangskomponenten liefert, da die Anzahl nf
der Flächen maximal 2nk /3 ist (doppeltes Abzählen der Flächen-Kanten-Inzidenzen), für
planare Graphen ohne Zweiecke“ die Beziehung nk ≤ 3ne − 6. Genauer: ne + nf − nk ≥ 2,
”
damit nk ≤ ne + nf − 2 ≤ ne + 2nk /3 − 2. Nun ist m(p) gleich dem Grad des Knotens p.
Damit ist m die Summe der Grade aller Knoten, m = 2nk ≤ 6(2n + I) − 12 < 12(n + I).
Zusammen ergibt dies die gewünschte Abschätzung.
¤
Satz 3.6 Die I Schnittpunkte von n Strecken können mit einem Algorithmus (Modifikation von Algorithmus 3.3) mit Laufzeit in O((n + I) log n) und Speicherbedarf in O(n)
berechnet werden.
3.2
Die doppelt verkettete Kantenliste
Datenstruktur 3.7 (Doppelt verkettete Kantenliste) Eine doppelt verkettete Kantenliste besteht aus 3 Datenlisten, je eine für Knoten, Flächen und Halbkanten.
• Der Datensatz zu einem Knoten vi besteht aus den Feldern
Knoten = vi , aus
Koordinaten = f (vi ) ∈ R2 , den Koordinaten des eingebetteten Punktes, und
InzidenteHalbkante, einem Verweis auf eine (beliebige) Halbkante mit Anfang
vi .
• Für Flächen fi besteht der Datensatz aus den Feldern:
Fläche = fi ,
Außenrand, eine Referenz auf eine Halbkante des Außenranden und
Innenränder, eine Menge von Referenzen auf je eine Halbkante jeden Loches.
• Für Halbkanten hi gibt es die Felder
Halbkante = hi ,
Anfang, eine Referenz auf den Anfangsknoten,
Gegenüber, die inverse (gegenläufige) Halbkante,
Algorithmische Geometrie, WS 2009/10
12
TUM, M9, Dr. Nico Düvelmeyer
3 SCHNITTPUNKTE VON STRECKEN
InzidenteFläche, die links liegende Fläche
Nachfolger, die nachfolgende benachbarte Halbkante im Rand der links liegenden Fläche, und
Vorgänger, die vorausgehende benachbarte Halbkante im Rand der links liegenden Fläche.
Dazu können jeweils noch weitere Attribute hinzukommen. Eine doppelt verkettete Kantenliste ist gültig, wenn sie tatsächlich der Aufteilung der Ebene durch einen ebenen
Graphen entspricht.
3.3
Berechnung der Überlagerung zweier Ebenenaufteilungen
Die Überlagerung zweier Ebenenaufteilungen ist eine neue Ebenenaufteilung, erzeugt
durch die entsprechenden aufgeteilten Originalkanten.
Auftrag 3.8
Gegeben: Zwei doppelt verkettete Kantenlisten für Ebenenaufteilungen S1 , S2 .
Gesucht: Doppelt verkettete Kantenlisten für Überlagerung Ü(S1 , S2 ) von S1 und S2 . Als
Attribute der Flächen sollen Paare der ursprünglichen Attribute gebildet werden.
Ein Großteil der Daten kann weiterverwendet werden, z.B. unzerschnittene Halbkanten.
Wir betrachten ein neues Gleitebenenverfahren, jetzt wird neben T und Q auch eine
doppelt verkettete Kantenliste D verwaltet. Anfangs ist D die Vereinigung von Kopien der
Ausgangsdaten. Wir lassen in unserer Betrachtung erstmal Flächendaten weg! Wir müssen
zudem Querverweise zwischen den Halbkanten in D und den Strecken in T verwalten.
Invariante unseres Verfahrens: alles über der Gleitgerade von D ist bereits korrekt berechnet!
Bei Ereignispunkten: T und Q werden wie gehabt aktualisiert. Waren in einem Schritt
nur Strecken von einer der beiden Eingangsaufteilung beteiligt, so ist nichts weiter zu
tun. Ansonsten sind weitere lokale Operationen nötig, um die Kantenverknüpfung neu
durchzuführen.
Beispiel 3.9 Kante k von S1 geht durch Knoten v von S2 . k wurde bisher durch 2 Halbkanten dargestellt, daraus werden jetzt vier! Bisherige Enden von k sind leicht korrigiert.
Im Punkt v muss die exakte zyklische Position bestimmt werden und dann entsprechend
die Verknüpftung durchgeführt werden.
Zeitaufwand für die Korrektur von k beim Ereignispunkt v: O(m(v)), wobei m(v) weiterhin
die Anzahl von Originalkanten ist, die zu v inzident sind (für die Suche der richtigen
Positionen in der zyklischen Reihenfolge).
Der Gesamtzeitaufwand für Halbkanten- und Knotenrekords ist in O((n + k) log n), wobei
n Summe der Komplexitäten von S1 und S2 , sowie k die Komplexität vom Ergebnis
bezeichnet. Dabei werden die Knoten- und Halbkantendatensätze korrekt berechnet bis
auf das Datenfeld InzidenteFläche.
Algorithmische Geometrie, WS 2009/10
13
TUM, M9, Dr. Nico Düvelmeyer
3 SCHNITTPUNKTE VON STRECKEN
3.3.1
Flächendaten
Wir bauen die Flächendatenliste komplett neu auf, basierend auf Zyklen von aufeinanderfolgenden Halbkanten.
Für Halbkantenzyklen müssen wir innere und äußere Ränder der Flächen unterscheiden!
Dies gelingt z.B. durch lokale Untersuchungen am global am weitestens links liegenden
Knoten (wenn nicht eindeutig: davon der unterste) des Zyklus. Für äußere Ränder ist der
orientierte Innenwinkel dort kleiner als 180◦ .
Weiterhin müssen wir die inneren Ränder einer Fläche mit dem äußeren Rand verknüpfen
und als eine einzige Fläche erkennen. Dazu bauen wir einen (ungerichteten, einfachen)
Hilfsgraphen G auf. Jeder äußere Rand entpricht genau einer Fläche, plus zusätzlich die
eindeutig bestimmte unbeschränkte Fläche. Knoten von G sind die Zyklen von Halbkanten
zusammen mit einem symbolischen Knoten ∞ für das unbeschränkte Gebiet.
Wir verbinden in G die Knoten x und y, wenn x für inneren Rand eines Loches steht und
im folgenden Sinne y links davon liegt. Sei p der am weitesten links (genauer: links unten)
liegende Knoten des Zyklus x. Liegt links von p unter allen Halbkanten zuerst eine nach
unten gerichtete Halbkante von y, so werden x und y verbunden. Liegt links von p gar
keine Halbkante mehr, so wird x mit ∞ verbunden.
Satz 3.10 Jede Zusammenhangskomponente des Graphen G stimmt genau mit der Menge
von Zyklen überein, die mit einer Fläche inzidieren.
Beweis Jedes Loch von f wird zu einem weiteren Zyklus verbunden, der ebenfalls f
berandet. Somit gehören alle Zyklen einer Zusammenhangskomonente zur selben Fläche.
Wir zeigen noch, das jeder Zyklus der ein Loch von f begrenzt auch mit dem Außenrand
von f zumindest indirekt verbunden ist. Anderenfalls gäbe es ein am weitesten links
liegendes Loch x von f das nicht mit dem Außenrand verbunden ist. Betrachten wir den
mit x über den linkesten Punkt verbunden Zyklus y, ergibt sich ein Widerspruch.
¤
Nach dem Gleitebenendurchlauf kann in Zeit O(n+k) die Flächenverknüpfung der doppelt
verketteten Kantenliste berechnet werden.
Speichern wir zusätzlich noch von allen Knoten die zugehörigen Seiteninformationen
während des Ebenendurchlaufs, können wir auch die Attribute der neuen Flächen allein durch lokale Betrachtungen effizient bestimmen. Dies erfordert eine Erweiterung der
Informationen, die in T gespeichert werden, und deren Aktualisierung an den Ereignispunkten.
Algorithmus 3.11
Eingabe: Zwei doppelt verkettete Kantenlisten für Ebenenaufteilungen S1 , S2 .
Ausgabe: Doppelt verkettete Kantenlisten D für Überlagerung Ü(S1 , S2 ). Als Attribute
der Flächen sollen Paare der ursprünglichen Attribute gebildet werden.
1: Funktion KartenÜberlagerung(S1 , S2 )
2:
Kopiere die Datenstrukturen für S1 und S2 in eine neue gemeinsame doppelt verkettete Kantenliste D.
3:
Berechne alle Schnittpunkte zwischen Kanten von S1 und S2 mit dem Gleitebenenverfahren SucheSchnittpunkte in Algorithmus 3.3. Zusätzlich zu den Änderungen
an T und Q ist bei den Ereignispunkten folgendes zu tun:
Algorithmische Geometrie, WS 2009/10
14
TUM, M9, Dr. Nico Düvelmeyer
3 SCHNITTPUNKTE VON STRECKEN
• Aktualisiere D entsprechend den lokalen Änderungen (siehe Beispiel 3.9) falls
Kanten von sowol S1 und S2 beteiligt sind.
• Speichere die Halbkante l(p) direkt links vom Ereignispunkt p zusätzlich in der
Repräsentation von p in der Datenstruktur D.
⊲ Nun ist D bis auf Seiteninformationen korrekt
Bestimme die Randzyklen von Ü(S1 , S2 ) beim Durchlaufen (Tiefensuche) von D.
Baue den Graph G mit Knotenn entsprechend den Randzyklen und Kanten, die
jedes Loch mit dem linken Nachbarn verbinden. Verwende dafür l(p). Bestimme die
Zusammenhangskomponenten von G.
6:
Für alle Zusammenhangskomponenten K von G mache
7:
C ← der eindeutige äußere Randzyklus von K. Lege einen neue FlächenDatensatz für die zugehörige Fläche f an. Setze Außenrand(f ) auf eine Halbkante
von C, und füge in Innenränder(f ) für alle Löcher in K je eine Halbkante ein.
Durchlaufe alle diese Randzyklen und setze alle Referenzen InzidenteFläche auf
f.
8:
Bestimme die Attribute aller neuen Flächen f durch lokale Informationen an jeweils einer Ecken von f .
4:
5:
Satz 3.12 Sei S1 eine Ebenenaufteilung der Komplexität n1 , S2 eine solcher der Komplexität n2 , und n := n1 +n2 . Die Überlagerung von S1 und S2 kann in Zeit O(n log n+k log n)
berechnet werden, wobei k die Komplexität der Überlagerung ist.
Folgerung 3.13 Für zwei ebene Polygone P1 , P2 mit n1 bzw. n2 Ecken kann P1 ∪ P2 ,
P1 ∩ P2 und P1 \ P2 jeweils in Zeit O((n + k) log n) berechnet werden, wobei n := n1 + n2
und k die Komplexität des Ergebnisses ist.
Bemerkung 3.14 Eine untere Schranke für den Worst-Case-Zeitaufwand der allgemeinen Schnittpunktbestimmung ist Ω(n log n + k). Aber es gibt auch O(n + k)-Algorithmen,
die ausnutzen, dass zwei gegebene Ebenenaufteilungen jeweils zusammenhängend sind.
Algorithmische Geometrie, WS 2009/10
15
TUM, M9, Dr. Nico Düvelmeyer
Herunterladen