📅  最后修改于: 2023-12-03 14:50:10.216000             🧑  作者: Mango
凸包是指包含给定点集的最小凸多边形或凸壳。其中最小凸多边形是指包含所有点的最小凸多边形,而凸壳则是指点集上所有点的凸包。Jarvis算法也称作包裹算法或礼物包装算法,是一种朴素的求解凸包的算法。
Jarvis算法的基本思路是从所有点集中选出一个左侧最靠近的点,然后逆时针扫描,每次选取下一个逆时针方向最接近的点加入凸包中。最终凸包构成的是所有点集中最小的凸多边形。
具体来说,该算法的核心过程分为三步:
接着,不断执行此过程直到回到起点。
以下代码是使用Java语言实现的Jarvis算法。
public static int cross(point a, point b, point c) {
return (b.x - a.x) * (c.y - a.y) - (b.y - a.y) * (c.x - a.x);
}
public static double dis(point a, point b) {
return Math.sqrt((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y));
}
public static point next(point p, ArrayList<point> lst) {
point nextP = lst.get(0);
for (int i = 1; i < lst.size(); i++) {
if (lst.get(i).y < nextP.y || (lst.get(i).y == nextP.y && lst.get(i).x < nextP.x)) {
nextP = lst.get(i);
}
}
return nextP;
}
public static ArrayList<point> Jarvis(ArrayList<point> lst) {
if (lst.size() <= 2) {
return lst;
}
point startP = lst.get(0);
for (int i = 1; i < lst.size(); i++) {
if (lst.get(i).x < startP.x || (lst.get(i).x == startP.x && lst.get(i).y < startP.y)) {
startP = lst.get(i);
}
}
ArrayList<point> res = new ArrayList<>();
res.add(startP);
point pre = startP;
while (true) {
point nextP = next(pre, lst);
if (nextP == startP) {
break;
}
res.add(nextP);
pre = nextP;
}
return res;
}
其中,point是个简单的二维点类型,具有x,y两个成员变量。
class point {
int x, y;
point(int x, int y) {
this.x = x;
this.y = y;
}
}
Jarvis算法虽然过程朴素,但实际应用广泛,尤其是对于小规模数据,其表现可以和更复杂的算法相当甚至超过。对于大规模数据,该算法的表现会有所下降,可以使用更高效的算法,如Graham扫描或快速凸包。