www.wikidata.de-de.nina.az
Der Graham Scan nach Ronald Graham 1972 ist ein effizienter Algorithmus zur Berechnung der konvexen Hulle einer endlichen Menge von Punkten in der Ebene Bei n displaystyle n Punkten liegt seine asymptotische Laufzeit in O n log n displaystyle mathcal O n cdot log n Animation des Graham Scan Algorithmus Inhaltsverzeichnis 1 Beschreibung 1 1 Vorbereitung 2 Hilfsfunktion 2 1 Berechnung 2 2 Anmerkung 3 Pseudocode 3 1 Unter Nutzung eines Stacks 3 2 Ohne Nutzung eines Stacks 4 Programmierung 5 Weblinks 6 EinzelnachweiseBeschreibung BearbeitenVorbereitung Bearbeiten nbsp Sortierung einer Punktmenge nach Winkel mit Bezugspunkt P 0 displaystyle P 0 nbsp Sei S P displaystyle S P nbsp eine endliche Punktmenge Der Algorithmus beginnt mit einem Punkt der Menge welcher garantiert ein Eckpunkt der konvexen Hulle ist Man sucht sich dazu den Punkt mit der kleinsten Ordinate Sind dies mehrere so sucht man sich aus diesen Punkten den mit der kleinsten Abszisse aus lexikographische Suche Diese Suche kann in O n displaystyle O n nbsp Schritten durchgefuhrt werden Nachdem der Startpunkt P 0 displaystyle P 0 nbsp gefunden wurde sortiert der Algorithmus die restlichen Punkte P displaystyle P nbsp in S displaystyle S nbsp nach aufsteigendem Winkel zwischen P 0 displaystyle P 0 nbsp P displaystyle P nbsp und der x Achse gegen den Uhrzeigersinn Haben dabei zwei Punkte den gleichen Winkel d h liegen mit P 0 displaystyle P 0 nbsp auf einer Linie sind kollinear mit P 0 displaystyle P 0 nbsp so wird der Punkt welcher naher an P 0 displaystyle P 0 nbsp liegt verworfen Hilfsfunktion Bearbeiten nbsp PAB und ABC sind positiv orientierte Dreiecke BCD ist negativ orientiert Oder anders C liegt links von AB D liegt rechts von BC Der Stack wird bis P A B C aufgebaut im nachsten Schritt wird C zugunsten von D entfernt In der nachfolgenden Rechnung muss wiederholt entschieden werden ob drei Punkte A x A y A displaystyle A x A y A nbsp B x B y B displaystyle B x B y B nbsp C x C y C displaystyle C x C y C nbsp in der Ebene ein positiv orientiertes Dreieck bilden Aquivalente Formulierungen dafur sind dass der Streckenzug A B C displaystyle ABC nbsp einen Knick nach links hat oder dass der Punkt C displaystyle C nbsp links der Strecke von A displaystyle A nbsp nach B displaystyle B nbsp bzw der Punkt B displaystyle B nbsp rechts von der Strecke von A displaystyle A nbsp nach C displaystyle C nbsp liegt Diese Aufgabe kann man durch Bestimmen aller relevanten Winkel losen oder einfacher durch die Berechnung einer Determinante T A B C displaystyle T A B C nbsp diese liefert das gewunschte Ergebnis mit weniger Rechenaufwand funf Subtraktionen zwei Multiplikationen und genauer Das Ergebnis bleibt fur rationale Koordinaten im rationalen Zahlenbereich welcher ohne Verlust von Genauigkeit im Computer abgebildet werden kann Das Ergebnis wird uber den folgenden Ausdruck berechnet T A B C 1 x A y A 1 x B y B 1 x C y C 1 x A y A 0 x B x A y B y A 0 x C x A y C y A x B x A y B y A x C x A y C y A x B x A y C y A x C x A y B y A lt 0 wenn C ist rechts von A B 0 wenn C ist auf A B gt 0 wenn C ist links von A B displaystyle begin aligned T A B C amp begin vmatrix 1 amp x A amp y A 1 amp x B amp y B 1 amp x C amp y C end vmatrix begin vmatrix 1 amp x A amp y A 0 amp x B x A amp y B y A 0 amp x C x A amp y C y A end vmatrix begin vmatrix x B x A amp y B y A x C x A amp y C y A end vmatrix amp x B x A y C y A x C x A y B y A amp begin cases lt 0 amp text wenn C text ist rechts von overrightarrow AB 0 amp text wenn C text ist auf overrightarrow AB gt 0 amp text wenn C text ist links von overrightarrow AB end cases end aligned nbsp Berechnung Bearbeiten nbsp Nach Winkel sortierte Punktmenge P 0 displaystyle P 0 nbsp wird als Startpunkt gewahlt da er den kleinsten Ordinatenwert hat P 1 displaystyle P 1 nbsp fallt heraus da er mit P 2 displaystyle P 2 nbsp und P 0 displaystyle P 0 nbsp kollinear ist S displaystyle S nbsp sei nun die sortierte Punktmenge Als Nachstes lauft man alle Punkte in S displaystyle S nbsp durch und pruft ob diese Eckpunkte der konvexen Hulle sind Es wird ein Stapelspeicher Stack angelegt auf welchem sich alle Eckpunkte der konvexen Hulle fur alle bereits abgearbeiteten Punkte befinden Zu Beginn liegen P 0 displaystyle P 0 nbsp und P 1 displaystyle P 1 nbsp auf dem Stapel Im k displaystyle k nbsp ten Schritt wird P k displaystyle P k nbsp zur Betrachtung herangezogen und berechnet wie er die vorherige konvexe Hulle verandert Aufgrund der Sortierung liegt P k displaystyle P k nbsp immer ausserhalb der Hulle der vorherigen Punkte P i displaystyle P i nbsp mit i lt k displaystyle i lt k nbsp Durch das Hinzufugen des Punktes kann es vorkommen dass bereits auf dem Stapel liegende Punkte nicht mehr zur neuen konvexen Hulle gehoren Diese Punkte mussen mittels der pop Operation vom Stapel entfernt werden Ob ein Punkt noch zur konvexen Hulle gehort oder nicht ermittelt man indem man berechnet ob P k displaystyle P k nbsp links oder rechts des Vektors PT2 PT1 liegt PT1 oberstes Element des Stapels PT2 Element direkt unter PT1 Liegt P k displaystyle P k nbsp links so bleibt PT1 weiterhin auf dem Stapel und P k displaystyle P k nbsp wird mit push auf dem Stapel abgelegt liegt P k displaystyle P k nbsp rechts so wird PT1 von der neuen konvexen Hulle verschluckt vom Stapel entfernt und die nachsten beiden oberen Punkte untersucht Dieser Test wird solange durchgefuhrt bis P k displaystyle P k nbsp links des Vektors PT2 PT1 oder nur noch P 0 displaystyle P 0 nbsp und ein weiterer Punkt auf dem Stapel liegt In beiden Fallen wird dann P k displaystyle P k nbsp auf dem Stapel abgelegt und mit dem nachsten Punkt P k 1 displaystyle P k 1 nbsp weitergerechnet Die folgende Abbildung zeigt ein Beispiel in welchem alle Falle des eben beschriebenen Tests auftreten nbsp Beispiel Graham Scan AlgorithmusIn nebenstehender Abbildung werden zunachst die Punkte Pt4 Pt3 Pt2 und P k 1 displaystyle P k 1 nbsp auf den Stack gelegt Zu jedem Zeitpunkt bilden die Punkte auf dem Stack ein konvexes Polygon gestrichelte Linien Erst als P k displaystyle P k nbsp hinzukommen soll fallen P k 1 displaystyle P k 1 nbsp und Pt2 wieder raus da sie zusammen mit P k displaystyle P k nbsp nicht konvex sind Die konvexe Hulle dieser Punktmenge besteht aus P 0 displaystyle P 0 nbsp Pt4 Pt3 und P k displaystyle P k nbsp P 0 displaystyle P 0 nbsp liegt dabei auf dem Stack ganz unten und P k displaystyle P k nbsp ganz oben Die Punkte des gesuchten konvexen Polygons konnen mit pop im Uhrzeigersinn vom Stapel geholt werden Anmerkung Bearbeiten Die Anzahl der push und pop Operationen ubersteigt die obere Grenze von 2 n displaystyle 2n nbsp n displaystyle n nbsp Anzahl der Punkte in der Eingabemenge nicht Die Berechnung ist also O n displaystyle mathcal O n nbsp Die Sortierung der Punkte nach Winkel kann mit jedem beliebigen Sortieralgorithmus durchgefuhrt werden z B Mergesort Dieser hat eine asymptotische Laufzeit von O n log n displaystyle mathcal O n log n nbsp Das bedeutet dass die Laufzeit des Algorithmus durch die Sortierung vorgegeben ist da O n O n log n O n log n displaystyle mathcal O n mathcal O n log n mathcal O n log n nbsp Pseudocode BearbeitenUnter Nutzung eines Stacks Bearbeiten Funktion GrahamScan Eingabe Punktemenge S P Ausgabe konvexe Hulle von S Beginn Funktion Sei S die nach dem Winkel zu P0 sortierte Punktemenge PUSH P0 PUSH P1 i 2 n Anzahl der Punkte in S Solange i lt n fuhre aus Sei Pt1 der oberste Punkt auf dem Stack Sei Pt2 der zweitoberste Punkt auf dem Stack Wenn Si links des Vektors Pt2 Pt1 liegt oder Stack enthalt 2 Elemente dann fuhre aus PUSH Si i i 1 Ansonsten fuhre aus POP Pt1 Ende Bedingung Ende Schleife Ende Funktion Ohne Nutzung eines Stacks Bearbeiten Funktion GrahamScan Eingabe Punktemenge S P Ausgabe konvexe Hulle von S Beginn Funktion Sei S die nach dem Winkel zu P0 sortierte Punktemenge i 1 Solange i S Wenn Si rechts des Vektors Si 1 Si 1 liegt dann fuhre aus i i 1 Ansonsten fuhre aus Entferne das Element Si aus S i i 1 Ende Bedingung Ende Schleife Ende Funktion Im Code sei punkte ein Array aus Punkten aus dem man mit punkte i das i te Element erhalt und welches schon nach dem Winkel zu punkte 0 sortiert ist Der Code verandert dieses Array indem die Elemente geloscht werden die nicht zur konvexen Hulle gehoren Programmierung BearbeitenDas folgende Beispiel in der Programmiersprache C zeigt die Implementierung des Graham Scan Algorithmus Die Punkte und die konvexe Hulle werden auf dem Hauptfenster gezeichnet Das Programm verwendet mehrere Klassen Die Methoden fur den eigentlichen Algorithmus werden in der Klasse GrahamScan deklariert 1 2 Code Schnipsel using System using System Collections Generic using System Drawing using System Windows Forms Klasse die die Methoden fur den Algorithmus Graham Scan deklariert class GrahamScan Diese Methode gibt das zweitoberste Element im Stack der Punkte zuruck private PointF GetNextToTopElement Stack lt PointF gt points PointF topElement points Peek points Pop PointF nextToTopElement points Peek points Push topElement return nextToTopElement Diese Methode gibt den Abstand der zwei Punkte zuruck private float GetDistance PointF point1 PointF point2 return point1 X point2 X point1 X point2 X point1 Y point2 Y point1 Y point2 Y Diese Methode bestimmt die Orientierung des drei Punkte Wenn die Punkte im Uhrzeigersinn sind wird der Wert 1 zuruckgegeben Wenn die Punkte im Gegenuhrzeigersinn sind wird der Wert 1 zuruckgegeben Wenn die Punkte kollinear sind wird der Wert 0 zuruckgegeben private int GetOrientation PointF point1 PointF point2 PointF point3 float area point2 Y point1 Y point3 X point2 X point2 X point1 X point3 Y point2 Y if area gt 0 Wenn das Vorzeichen positiv ist sind die Punkte im Uhrzeigersinn return 1 if area lt 0 Wenn das Vorzeichen negativ ist sind die Punkte im Gegenuhrzeigersinn return 1 return 0 Wenn der Flacheninhalt gleich 0 ist sind die Punkte kollinear Diese Klasse implementiert eine Vergleichsmethode fur das Sortieren der Punkte class PointComparer Comparer lt PointF gt public PointF center public GrahamScan grahamScan Vergleichsmethode die die Punkte in Bezug auf den Punkt center sortiert public override int Compare PointF point1 PointF point2 int orientation grahamScan GetOrientation center point1 point2 if orientation 0 if grahamScan GetDistance center point2 gt grahamScan GetDistance center point1 return 1 return 1 return orientation Diese Methode gibt eine Liste der Punkte der konvexen Hulle zuruck public List lt PointF gt GetConvexHull List lt PointF gt points List lt PointF gt convexHull new List lt PointF gt Initialisiert die Liste der Punkte der konvexen Hulle float minimumY points 0 Y int indexOfMinimum 0 int numberOfpoints points Count Diese for Schleife durchlauft die verbleibenden Punkte und ermittelt den untersten Punkt und bei Gleichheit den Punkt ganz links for int i 1 i lt numberOfpoints i float y points i Y if y lt minimumY minimumY y amp amp points i X lt points indexOfMinimum X minimumY points i Y indexOfMinimum i Setzt den untersten Punkt an die erste Position PointF point points 0 points 0 points indexOfMinimum points indexOfMinimum point Initialisiert das Objekt das die Vergleichsmethode bereitstellt PointComparer pointComparer new PointComparer pointComparer center points 0 pointComparer grahamScan this points Sort pointComparer Sortiert die Punkte in Bezug auf den ersten Punkt Wenn zwei oder mehr Punkte den gleichen Winkel mit dem Punkt point bilden werden alle entfernt ausser dem Punkt der am weitesten vom Punkt point entfernt ist int index 1 for int i 1 i lt numberOfpoints i Entfernt jeweils das Element mit Index i solange die Punkte der gegebenen Elemente kollinear sind while i lt numberOfpoints 1 amp amp GetOrientation pointComparer center points i points i 1 0 i points index points i index if index lt 3 Wenn weniger als 3 Punkte vorhanden sind wird eine leere Liste zuruckgegeben return convexHull Erzeugt einen Stack und fugt die ersten 3 Punkte hinzu Stack lt PointF gt pointStack new Stack lt PointF gt pointStack Push points 0 pointStack Push points 1 pointStack Push points 2 Diese for Schleife durchlauft die verbleibenden Punkte for int i 3 i lt index i Entfernt jeweils das oberste Element des Stack solange die Punkte der gegebenen Elemente im Uhrzeigersinn sind while pointStack Count gt 1 amp amp GetOrientation GetNextToTopElement pointStack pointStack Peek points i 1 pointStack Pop pointStack Push points i Fugt die Punkte des Stack der Liste der Punkte der konvexen Hulle hinzu while pointStack Count 0 convexHull Add pointStack Peek pointStack Pop return convexHull Klasse fur das Hauptfenster public partial class MainForm Form private Graphics graphics private List lt PointF gt points new List lt PointF gt Liste der Punkte private List lt PointF gt convexHull new List lt PointF gt Liste der Punkte der konvexen Hulle private double x1 y1 x2 y2 public MainForm x1 100 y1 100 x2 700 y2 700 Setzt die Koordinaten der Eckpunkte der quadratischen Zeichenflache Random random new Random Initialisiert den Zufallsgenerator int numberOfPoints 100 for int i 0 i lt numberOfPoints i Diese for Schleife erzeugt 100 zufallige Punkte innerhalb der quadratischen Zeichenflache PointF point new PointF point X float random NextDouble x2 x1 x1 point Y float random NextDouble y2 y1 y1 points Add point Fugt den Punkt der Liste hinzu GrahamScan grahamScan new GrahamScan Erzeugt ein Objekt der Klasse GrahamScan convexHull grahamScan GetConvexHull points Aufruf der Methode die die konvexe Hulle zuruckgibt InitializeComponent Text Konvexe Hulle Width 800 Height 800 graphics CreateGraphics Erzeugt ein Grafikobjekt fur das Zeichnen auf dem Hauptfenster Paint OnPaint Verknupft die Ereignisbehandlungsmethode mit dem Paint Ereignis des Hauptfensters Diese Methode wird aufgerufen wenn das Hauptfenster gezeichnet wird private void OnPaint object sender PaintEventArgs e for int i 0 i lt points Count i graphics FillRectangle new SolidBrush Color FromArgb 0 0 0 points i X 1 points i Y 1 2 2 Zeichnet die Punkte int numberOfPoints convexHull Count for int i 0 i lt numberOfPoints i graphics DrawLine new Pen Color FromArgb 0 0 255 convexHull i convexHull i 1 numberOfPoints Zeichnet die Kanten der konvexen Hulle Weblinks BearbeitenErklarungen samt Visualisierung des Verfahrens Computational Geometry in C Second Edition Erklarung und Pseudocode Animation des Graham Scan AlgorithmusEinzelnachweise Bearbeiten Rosetta Code Convex hull GeeksforGeeks Convex Hull Abgerufen von https de wikipedia org w index php title Graham Scan amp oldid 217396752