凸包算法

本文介绍了使用葛立恒(Graham)扫描法实现凸包算法的详细步骤。首先找到最下边的点,然后按极角排序,接着利用栈来维护凸包,判断点是否使序列形成左转。算法时间复杂度为O(n^2)。最终得出凸包并展示了核心代码。
摘要由CSDN通过智能技术生成

凸包算法

本次算法采用葛立恒(Graham)扫描法,由于排序方法使用选择排序,总时间复杂度为O(n^2)。

算法思路

第一步:找到最下边的点,如果有多个点纵坐标相同的点都在最下方,则选取最左边的。在右图中这个点是P。这一步只需要扫描一遍所有的点即可。
第二步:将所有的点按照相对于第一步中的得到的点P的极角大小进行排序。注意这一步并不需要真的通过计算反三角函数来获取与x轴夹角的大小。可以直接使用该点与P点连线的斜率,或者由P点到该点向量的与沿x轴单位向量的点积来减少计算量。可以使用诸如快速排序堆排序之类的算法进行排序,时间复杂度。

第三步:维护一个栈,以保存当前的凸包。按第二步中排序得到的结果,依次将点加入到栈中,如果正在考虑的点与栈顶的两个点不是“向左转”的,就表明当前栈顶的点并不在凸包上,而我们需要将其弹出栈,重复这一个过程直到正在考虑的点与栈顶的两个点是“向左转”的。右边的图解给出了“向左转”和“向右转”的示意:

  • 刚开始的两个点P、A直接入栈。
  • 在点B加入时,P->A->B就构成左转,因此直接加入点B即可。
  • 接下来加入点C,A->B->C还是构成左转,因此直接加入点C。
  • 继续加入点D时,B->C->D就变成右转了,此时可以观察到如果将BD连线,C将被包含在多边形的内部,因此点C出栈。注意需要继续检查A->B->D是左转还是右转,如果还是右转的话B点需要继续出栈,以此类推。这个例子比较简单,A->B->D已经是左转了,D点可以入栈。
  • 最后回到P点,B->D->P是左转,算法完成,所求凸包为四边形PABD。

结果

结果

核心代码

import java.awt.Point;
import java.util.*;

public class GrahamHull {
   
    private Point[] points;
    private Point lowerPoint;
    private Stack<Point> track;

    GrahamHull(Set<Point> points){
   
        this.points = new Point[points.size()];
        int i = 0;
        for(Point point : points){
   
            this.points[i++] =new Point(point);
        }
        track = new Stack<>();
    }

    public GrahamHull calc(){
   
		setLowerPoint()
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值