首页 > 编程语言 >凸包算法

凸包算法

时间:2022-09-23 10:01:51浏览次数:69  
标签:const Point 凸包 pps 算法 points ans

凸包的概念:

在某个二维平面上的给定一个点集,凸包就是将最外层的点连接起来构成的凸多边形,它能包含点集中所有的点。

凸包算法

从点集中获取凸包的方法比较常用的有Jarvis步进法,Graham扫描法和Andrew算法,在时间性能(速度)上,Jarvis步进法<Graham扫描法<Andrew算法。

Jarvis步进法

凸包之Jarvis步进法_H煊的博客-CSDN博客_jarvis步进法

Graham扫描法

//点
struct Point
{
    float X, Y;
    Point() :X(0.0f), Y(0.0f){}
    Point(float x, float y) : X(x), Y(y){}
    bool operator==(const Point& other) { return (abs(X - other.X) + abs(Y - other.Y)) < 0.00001f; }
    bool operator!=(const Point& other) { return !((*this) == other); }
    friend std::ostream& operator<<(std::ostream& out, const Point& p)
    {
        out << '(' << p.X << ", " << p.Y << ')';
        return out;
    }
};

//Graham扫描法
class ConvexHullAlgorithm
{
    //根据原点base,求target点的极坐标的角度的cos值
    //由于base的y值是最小值,所以角度angle(target)区间是[0,180], 
    //且val = cos(angle(target))在[0,180]→[-1,1]是一一映射的。
    //因此可以用val代替angle(target)
    float CalPolarAngle(const Point& base, const Point& target) const
    {
        float xDis = target.X - base.X;
        float yDis = target.Y - base.Y;
        float dis = std::sqrtf(xDis * xDis + yDis * yDis);
        return xDis / dis;
    }
    //只是为了方便排序而设的结构
    struct PolarPoint
    {
        float polarAngle;
        Point point;
        PolarPoint():polarAngle(0.0f),point(0.0f,0.0f){}
    };
    //利用叉乘判断a->b->c是否逆时针排序
    bool IsAnticlockwise(const Point& a, const Point& b, const Point& c) const
    {
        Point ab(b.X - a.X, b.Y - a.Y);
        Point bc(c.X - b.X, c.Y - b.Y);
        return ab.X * bc.Y - ab.Y * bc.X > 0;
    }
public:
    //公开接口:获取凸包
    std::vector<Point> ConvexHull(std::vector<Point>& points)
    {
        int size = points.size();
        if (size <= 3) return points;
        std::vector<PolarPoint> pps(size);
        //找出y值最小的点base
        auto minit = std::min_element(points.begin(), points.end(), [](const Point& lhs, const Point& rhs) {return lhs.Y < rhs.Y; });
        std::swap(*minit, *points.begin());
        Point base = points[0];
        //计算基于base为原点的其他每个点极点坐标角度的cos值
        for (int i = 1; i < size; ++i)
        {
            pps[i].point = points[i];
            pps[i].polarAngle = CalPolarAngle(base, points[i]);
        }
        //根据极点坐标角度的cos值进行排序
        std::sort(pps.begin() + 1, pps.end(), [](const PolarPoint& lhs, const PolarPoint& rhs) {return lhs.polarAngle > rhs.polarAngle; });
        std::vector<Point> ans;
        ans.push_back(pps[0].point);
        ans.push_back(pps[1].point);
        int num = 1;
        //找出凸包
        for (int i = 2; i < size; ++i)
        {
            while(num > 0 && !IsAnticlockwise(ans[num - 1], ans[num], pps[i].point))
            {
                ans.pop_back();
                --num;
            }
            ans.push_back(pps[i].point);
            ++num;
        }
        return ans;
    }
};                

Andrew算法

Andrew算法是Graham扫描法的改进法,待我再研究一下。

 

标签:const,Point,凸包,pps,算法,points,ans
From: https://www.cnblogs.com/mshentaiBlog/p/16721676.html

相关文章

  • 「浙江理工大学ACM入队200题系列」问题 A: 零基础学C/C++34—— 3个数比较大小(冒泡排
    深夜写的,代码都还没来得及跑一便,可能有错误,欢迎指出,后续会检验一遍并修改错误.本题是浙江理工大学ACM入队200题第四套中的A题,同时给出了冒泡排序和选择排序算法......
  • 算法练习-第二天【数组】
    数组977.有序数组的平方参考:代码随想录977.有序数组的平方看完题目的第一想法根据题意直接每个元素求平方,然后排个序,提交。时间复杂度O(\(nlogn\))。funcsortedSqua......
  • 算法设计与分析课-实验三-动态规划
    算法设计与分析课实验三第一题矩阵连乘问题:分析:该问题求矩阵连乘积最少乘次数,对于两个矩阵A(i行j列)和B(j行n列),他们相乘的乘次数为ijn,对于两个矩阵只有它们的列和行......
  • CSP 2022 备战 贪心算法
    基本思路:1.建立数学模型来描述问题2.把求解的问题分成若干个子问题3.对每一子问题求解,得到子问题的局部最优解4.把子问题的局部最优解合并成一个解贪心的使用前提:局部......
  • KMP算法
    朴素的模式匹配算法朴素算法就是以主串的每一个字符作为子串的开头,与要匹配的字符串(称为模式串)进行匹配,匹配失败则主串退回到这次匹配首位的下一位,重新进行匹配。主......
  • python基础__十大经典排序算法
    用Python实现十大经典排序算法!排序算法是《数据结构与算法》中最基本的算法之一。排序算法可以分为内部排序和外部排序,内部排序是数据记录在内存中进行排序,而外部排序......
  • 一段式SM3算法的实现
    C语言#pragmaonce//C语言实现的一段式SM3算法#include<stdio.h>#include<memory>//定义初始值IV,初始值IV是一个常数unsignedcharIV[256/8]{0x73,0x80......
  • Vue源码解析——虚拟DOM和diff算法
    前置环境:1.手写h函数vnode.js//默认暴露exportdefaultfunction(sel,data,children,text,elm){return{sel,data,children,text,elm}}h.jsim......
  • 算法题中常用的C++函数
    一、向vector容器中增添元素1、在末尾增添一个元素push_back()2、在任意地方插入一个或多个元素insert()#include<iostream>#include<vector>//注意这......
  • Hash算法
    Hash算法是什么哈希(hash)也翻译作散列。Hash算法,是将一个不定长的输入,通过散列函数变换成一个定长的输出,即散列值,这个值就是Hash值。Hash算法只是一个定义,并没有规定具体......