Disclaimer: Diese Mitschrift ist als Ergänzung zur Vorlesung gedacht. Wir erheben keinen Anspruch auf Vollständigkeit und Korrektheit. Wir sind jederzeit froh um Hinweise zu Fehlern oder Unklarheiten an grafdan@ethz.ch.
Wenn Sie an dieser Mitschrift mitarbeiten möchten, melden Sie sich hier.
Heute wird's ganz leicht: Wir verlassen die Graphentheorie und beschäftigen uns mit der algorithmischen Seite der Geometrie.
Warum ist Geometrie überhaupt was algorithmisch Interessantes? Beim Sortieren, den Wörterbüchern, dem Hashing und allem was wir bis jetzt angeschaut haben handelte es sich immer um Mengen von Zahlen, also eindimensionalen Objekten. Nun betrachten
Wir stellen uns folgendes. In der 2 Dimensionalen Ebene, habe wir Punkten, die irgiendwie verteilt sind. Die Frage, die wir jetzt Stellen ist, dass wie koennen wir die konvexe Huelle erstellen. Die konvexe Huelle ist natuerlich die kleinste konvexe Huelle, die alle Punkte enthaelt.
Für eine Punktmenge in der Ebenen ist die konvexe Hülle, die kleinste konvexe Teilmenge der Ebene, welche alle Punkte erhält. Wir erinnern uns: Eine Menge ist konvex, wenn alle gewichteten Mittel von Punkten aus der Menge auch in der Menge liegen.
TODO Skizze
Wir beobachten, dass die konvexe Hülle immer durch ein Polygon bestehend aus einiger der Punkte beschrieben wird.
Wie koennen wir eine Algorithmus herausfinden, die diese keilste konvexe Polygon beschreibt?
Wie würden wir das physisch machen? Wir nehmen ein Brett ein, dass unsere euklidsche Ebene darstellt und schlagen einen Nagel für jeden Punkt ein. Nun nehmen wir eine Schnur und legen sie um alle Nägel herum und ziehen sie straff.
Ein solches Nagel & Schnur Verfahren kostet nur \O(n)$ Zeit. Aber wir haben im Rechner keine Nagel & Schnur Operation. 😢
Was können wir algorithmisch tun? Wir ueberlegen uns eine einfache Algorithmus
Pruefe jede Verbindung ob es auf der Huelle liegt. (Wie kann man das ueberpruefen ? Think about it!).
Wir verbinden zwei Pukten mir einer Gerade und schauen on alle uebrig gebliebene Punkten auf den gleichen Seiete der Gerade liegen.
Diese Gerade zu konsturieren kostet
Versuchen wir den Schnur-Algorithmus zu simulieren. Starten wir am Punkt ganz links und lassen die Schnur gedanklich dort herunterhängen. Nun ziehen wir die Schnur nach rechts und möchten wissen an welchem Punkt die Schnur zuerst aneckt. Dazu bilden wir vom Startpunkt aus die Gerade zu jedem anderen Punkt und suchen diejenige mit der kleinsten Steigung (als dem steilsten Abfall). Anschliessend haben einen zweiten Punkt auf der Hülle gefunden und können das Herumziehen der Schnur von dort aus weitersimulieren.
Dieses Verfahren heisst Jarvis March, weil wir so um die Hülle herummarschieren.
starte mit einem Punkt auf der Hülle
wiederhole bis einmal rundherum
ermittle den nächsten Hüllenpunkt
durch Inspektion aller Winkel
Jeder Schleifendurchlauf kostet
Versuchen wir es wieder mal mit unserem Lieblingsalgorithmenentwurfsprinzip: Induktion!
Wir wählen einen extremalen Startpunkt
TODO Skizze
Für einen neuen Punkt, wissen wir dass er auf der konvexen Hülle liegt. Wir fügen ihn auf den Stack und überprüfen ob die letzten drei Punkte immer noch eine Rechtsdrehung darstellen. Falls nicht, so können wir den zweitletzten Punkt der Hülle entfernen und wiederholen diesen Prüfschritt, bis wir wieder nur noch Rechtsdrehungen auf der Hülle haben.
Da jeder Punkt höchstens einmal auf die Hülle eingefügt und entfernt wird und wir nur so viele Drehungen testen, wie wir die Hülle verändern, kostet dieser Scan nach Winkel nur lineare Zeit. Das Teuereste ist also das initiale Sortiern.
Gesamtlaufzeit von diesem Graham's Scan ist somit
Statt nach Winkel zu sortieren und dann radial durchzugehen, können wir auch lexikographisch, also von links nach rechts, sortieren und
sortiere Punkte von links nach rechts
spaziere lienar durch
falls zweimal gebogen, geh zurueck
schau auf die Punkte, falls auf der Huelle ligt nimm
sonst schau andere Punkte
Die Gesamtlaufzeit dieser Algorithmus ist
Wie überprüfen wir, ob ein gegebenes Polygon wirklich konvex ist?
Wenn wir nur testen, ob wir nur Rechtsdrehungen haben, kann das schief gehen:
Wir müssen also aufpassen, dass sich das Polygon nicht selbst schneidet. Wie prüfen wir ob sich zwei Segmente schneiden?[1]
Gegeben eine Menge von waagrechten und senkrechten Liniensegmenten. Kreuzen sich zwei der Segmente?
Ein Anwendung für dieses Problem ist das Chipdesign. Wir haben Milliarden von Leiterbahnen und wollen rasch überprüfen, dass sich die Leiterbahnen nicht kreuzen.
Wie überprüfen wir überhaupt, ob sich zwei Liniensegmente kreuzen?[1] Für je ein horizontales und vertikales Segment, beschrieben durch
Wie können wir nun für alle
So wie vorher führen wir Induktion von links nach rechts durch. Wir stellen uns eine Linie vor, welche von links nach rechts geht. (genannt Scanline oder Sweepline)
Ereignisse entlang dieser Linie sind die sogenannten Haltepunkte. Also in unserem Problem zwei Punkte für die die horizontalen Segmente und einen Haltepunkt für senkrechte Segmente.
Für die horizontalen Segmente sagen wir, dass es schlafend ist, falls es noch komplett rechts der Scanline ist. Ein horizontales Segment ist tot, falls die Scanline schon komplett darüber hinweg ist. Falls die Scanline noch im Bereicht des Segments liegt, nennen wir das Segment aktiv.
Kommt nun ein vertikales Segment
Wir haben also drei Operationen:
Die effizienteste Datenstrucktur für diese Operationen ist ein balancierter Suchbaum. Wir wählen deshalb einen AVL-Baum. Wir speichern die aktiven, horizontalen Segmente in den Blättern des AVL-Baums und ordnen nach
Bei einem vertikalen Segment
TODO Skizze
Mit dieser Datenstrucktur erreichen wir eine Gesamtlaufzeit von
Für einen Chipdesigener ist es aber nicht sonderlich praktisch zu hören: "Dein Design ist kaputt!" Oder: "Hier ist ein beliebiger Fehler!" Wir möchten lieber gleich alle Schnitte kennen.
Um Schnitte Aufzaehlen zu koennen , berichten wir laut doppelt verketteter Blattliste, welche uns die Losung in
Wenn wir einfach
Die Anzahl diesen Teibaumen sund hoechstens logarithmisch viele also
TODO Skizze Kanonische Überdeckung des Intervalls
Damit können wir nun eine Anfrage nach den Anzahl Elementen in einem Interval rasch beantworten, egal wie gross die Antwort ist. Wir zählen also für jedes vertikale Segment die Anzahl Schnitte und addieren einfach auf. Damit ist auch die Gesamtlaufzeit