2.2 Naiver Ansatz: SlowConvexHull
Idee
Direkte Umsetzung des Kantenkriteriums: Probiere jede mögliche gerichtete Kante aus und prüfe, ob irgendein anderer Punkt links davon liegt. Wenn nein, ist es eine Hüllkante.
Algorithmus (Folie 8)
1 SortedList SlowConvexHull(PointSet P)
2 {
3 PointSet E = ∅;
4 for all (geordnete Paare (p,q) ∈ P² mit p ≠ q) {
5 valid = true;
6 for all (Punkte r ∈ P \ {p,q}) {
7 if (r liegt links der gerichteten Geraden pq)
8 valid = false;
9 }
10 if (valid) füge die gerichtete Kante pq zu E hinzu;
11 }
12 SortedList L = ConstructSortedList(E);
13 return L;
14 }
Zeile für Zeile:
- Zeile 4: Geordnete Paare, d.h. und werden beide getestet. Das ist nötig, weil nur eine der beiden Richtungen im Uhrzeigersinn läuft.
- Zeilen 6–9: Teste alle übrigen Punkte mit dem Orientierungstest. Ein einziger Punkt links reicht, um die Kante zu verwerfen.
- Zeile 10: Überlebt die Kante, wird sie gemerkt.
- Zeile 12: enthält die Hüllkanten unsortiert.
ConstructSortedListverkettet sie zu einem Polygon: Beginne mit einer Kante , suche die Kante, die bei beginnt, usw.
Interaktiv durchspielen: Jeder Schritt testet eine gerichtete Kante. Rot schattiert ist die linke Seite – liegt dort ein Punkt (rot umkreist), fliegt die Kante raus. ⏩ springt zur nächsten gültigen Kante.
Korrektheit
Der Algorithmus ist (fast) korrekt:
- Rundungsfehler der Gleitkommaarithmetik werden vernachlässigt (Real-RAM-Modell).
- Die Zeilen 3–11 liefern eine unsortierte Liste aller Kanten der konvexen Hülle.
- Aber: Es gibt degenerierte Fälle!
Der degenerierte Fall: kollineare Punkte
Liegt ein Punkt genau auf der Geraden durch und , ist weder links noch rechts.
Im Beispiel unten liegen drei Punkte auf der unteren Hüllkante. Spring mit ⏩ durch die gültigen Kanten: Akzeptiert wird nur die lange Kante, nicht die Teilstücke über den mittleren Punkt.
Bei „links“ = (strikt) passiert Folgendes:
- , und werden alle drei als gültig akzeptiert. enthält überlappende Kanten, und
ConstructSortedListfindet bei zwei Nachfolger.
Bei „links“ = :
- Keine der drei Kanten wird akzeptiert, denn jeweils der dritte Punkt liegt „links“. Die Hülle hat ein Loch.
Korrekt ist: ist gültig, wenn alle anderen Punkte rechts liegen oder kollinear auf der Strecke (nicht dahinter oder davor). Dann ist nur gültig, und ist keine Ecke.
Solche Sonderfälle kommen bei Graham's Scan wieder und müssen dort genauso bedacht werden.
Laufzeit (Folie 10)
| Zeile | Aufwand |
|---|---|
| 4 | geordnete Paare |
| 6 | je Punkte |
| 7 | Orientierungstest: primitiv, |
| ⇒ 3–11 | |
| 12 | Verketten per Brute Force: für jede der Kanten den Nachfolger unter allen Kanten suchen, also |
| Gesamt |
Kann man das verbessern? Ja, deutlich. Der naive Ansatz verschwendet Arbeit: Er testet Kandidatenkanten, obwohl höchstens davon Hüllkanten sind. Die folgenden Algorithmen erzeugen Hüllkanten gezielter.