ConvexHull凸包算法之Gift-Wrapping

首先我们介绍凸包问题的定义

给定平面上一堆点集,输出位于凸包上的点。如下所示:输入如下这么多点集,输入P0,P1,P3,P10,P12

接下来讲解比较简单的Gift−Wrapping 算法
1.算法简介
我们发现任意凸包上的点,你会发现以该点建立一个极角坐标系,该点连结其它所有点的极角中,该点逆时针方向的第一凸包点到该点极角最小,例如P0,到所有点的极角中P0P1极角最小。
算法中首先找到最左边的点,这个点必然在凸包上,然后计算该点连接点极角最小的,这里计算有技巧,算法中进行toright测试,直到找到到最右端的点,找到P1后,就可以从P1开始,接着顺次找到P2,又以P2为起点……

2.时间复杂度
因为每次的起点都是上次找到的凸包点,因此外层循环的复杂度为O(H),H为凸包上的点,内层循环每次都会全部遍历点,因此时间复杂度为 O(n) ,因此总的是间复杂度为 O(nH) ,在一般情况下 凸包上的点的期望为logn ,算法复杂度为 O(nlogn) ,极端情况下,如下所示,所有点都在类似圆弧上的话,外层循环也是n,因此会达到O(n^2)。
3.JAVA实现

下面给出源代码

public static Set<Point> convexHull(Set<Point> points) {
        if (points.size() <= 3) return points;
        Set<Point> convexHullPoints = new HashSet<Point>();
        Point a = new Point(Double.MAX_VALUE, Double.MAX_VALUE);
        for (Point i : points) {
            if (i.x() < a.x() || (i.x() == a.x() && i.y() < a.y()))
                a = i;
        }
        Point curPoint = a, minPoint = null, lastPoint = a;
        double x1 = 0.0, y1 = -1.0;
        do {
            convexHullPoints.add(curPoint);
            double minTheta = Double.MAX_VALUE, x2 = 0.0, y2 = 0.0;
            for (Point i : points) {
                if ((!convexHullPoints.contains(i) || i == a) && (i != lastPoint)) {
                    double x3 = i.x() - curPoint.x(), y3 = i.y() - curPoint.y();
                    double Theta = Math
                            .acos((x1 * x3 + y1 * y3) / Math.sqrt(x1 * x1 + y1 * y1) / Math.sqrt(x3 * x3 + y3 * y3));
                    // System.out.println(i.x() + " " + i.y() + " " + Theta);
                    if (Theta < minTheta || (Theta == minTheta && x3 * x3 + y3 * y3 > Math.pow(i.x() - minPoint.x(), 2)
                            + Math.pow(i.y() - minPoint.y(), 2))) {
                        minPoint = i;
                        minTheta = Theta;
                        x2 = x3;
                        y2 = y3;
                    }
                }
            }
            x1 = x2;
            y1 = y2;
            lastPoint = curPoint;
            curPoint = minPoint;
            // System.out.println(curPoint.x() + " " + curPoint.y());
        } while (curPoint != a);
        return convexHullPoints;
    }

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值