1. 程式人生 > >Convex Hull:O(h*n)演算法 Jarvis March

Convex Hull:O(h*n)演算法 Jarvis March

課程:計算幾何

書籍:計算幾何:演算法與應用

Jarvis March演算法也是一種遞增式的思路。以極邊的一個端點為起點,來查詢另一條極邊。以此進行下去,最後構成一個環路時(極點的末端等於最初的起始端點)。凸包構造結束。

關於以一個極邊為起始點的一天極邊。可以用ToLeft測試進行比較,就如同O(n^2)中對點集逆時針排序那樣。

關於如何確定起始點,我們選取字典序最小的點作為起始點(Y值最小的點,如果存在多個Y最小值一樣的點,再選取X最小的點),起始方向,我們可隨意設定。

程式碼:
Point.h 沒有變化

Main.cpp

/*  indere 2018/6/23
*   O(hn)構造凸包演算法思路為:Jarvis March
*   輸入:頂點數以及頂點座標
*   輸出:極點編號(看情況是否按Counter-Clockwise輸出)
/

/*
10
7 9
-8 -1
-3 -1
1 4
-3 9
6 -4
7 5
6 6
-6 10
0 8
*/
#include "Point.h" Point *points; int pointsize; void Initialize(); //初始化points陣列 void ConstructConvexHull(Point* points); //根據Point陣列資訊 構造凸包 int LTL(Point* points); //得到頂點陣列中字典序最小的索引 int ToLeft(Point v1, Point v2, Point s); // int main() { Initialize(); ConstructConvexHull(points); for
(int i = 0; i < pointsize; i++) { if (points[i].isExtremePoint) cout << points[i]; } return 0; } void Initialize() { cin >> pointsize; points = new Point[pointsize]; for (int i = 0; i < pointsize; i++) { float x, y; cin >> x >> y; points[i] = Point(i + 1
, x, y); } } void ConstructConvexHull(Point* points) { for (int i = 0; i < pointsize; i++) { points[i].isExtremePoint = false; } int ltl = LTL(points); int begin, end; begin = ltl; do { points[begin].isExtremePoint = true; end = -1; for (int i = 0; i < pointsize; i++) { if (i != begin && i != end && (end == -1 || ToLeft(points[begin], points[end], points[i]) == -1)) end = i; } begin = end; } while (begin != ltl); } int LTL(Point* points) { int k = 0; for (int i = 1; i < pointsize; i++) { if (points[k].y > points[i].y || (points[k].y == points[i].y && points[k].x > points[i].x)) { k = i; } } return k; } int ToLeft(Point v1, Point v2, Point s) { float result = (v2.x *s.y + v1.x * v2.y + v1.y * s.x) - (v1.y * v2.x + v1.x * s.y + v2.y * s.x); if (result > 0.0f) //左側 return 1; if (result == 0.0f) //共線 return 2; if (result < 0.0f) //右側 return -1; }

這裡寫圖片描述