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

本文介绍了一种构建凸包的经典算法——Jarvis March算法。该算法以递增方式从一个极边的端点开始,逐步查找下一个极边,直至构成闭合环路。文中详细解释了如何选择起始点,并通过代码示例展示了算法的具体实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

课程:计算几何
书籍:计算几何:算法与应用

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;
}

这里写图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值