Convex Hull:O(h*n)演算法 Jarvis March
阿新 • • 發佈:2019-01-31
課程:計算幾何
書籍:計算幾何:演算法與應用
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;
}