c++ 使用 Graham 扫描的凸包(Convex Hull using Graham Scan)

news2024/10/2 2:31:16

先决条件:

如何检查两个给定的线段是否相交?

c++ https://blog.csdn.net/hefeng_aspnet/article/details/141713655
java https://blog.csdn.net/hefeng_aspnet/article/details/141713762
python https://blog.csdn.net/hefeng_aspnet/article/details/141714389
C# https://blog.csdn.net/hefeng_aspnet/article/details/141714420
Javascript https://blog.csdn.net/hefeng_aspnet/article/details/141714442 

贾维斯算法

 c++ https://blog.csdn.net/hefeng_aspnet/article/details/141716082
java https://blog.csdn.net/hefeng_aspnet/article/details/141716363
python https://blog.csdn.net/hefeng_aspnet/article/details/141716444
C# https://blog.csdn.net/hefeng_aspnet/article/details/141716403
Javascript https://blog.csdn.net/hefeng_aspnet/article/details/141716421 

        凸包是包含给定点集的最小凸多边形。它是计算几何学中一个有用的概念,在计算机图形学、图像处理和碰撞检测等各个领域都有应用。

凸多边形是所有内角都小于180度的多边形。可以为任意点集构造凸包,无论这些点如何排列。

格雷厄姆扫描算法:
        格雷厄姆扫描算法是一种简单而有效的算法,用于计算一组点的凸包。它的工作原理是迭代地将点添加到凸包中,直到所有点都添加完毕。

        该算法首先找到 y 坐标最小的点。该点始终位于凸包上。然后,该算法根据剩余点相对于起点的极角对它们进行排序。

        然后,算法会迭代地将点添加到凸包中。在每个步骤中,算法都会检查添加到凸包中的最后两个点是否形成右转。如果是,则将最后一个点从凸包中移除。否则,将排序列表中的下一个点添加到凸包中。

当所有点都被添加到凸包时,算法终止。

Graham Scan的实现:

第一阶段(排序点):
        实现格雷厄姆扫描算法的第一步是按照点相对于起点的极角对点进行排序。
        一旦点排序完毕,起点就会添加到凸包中。一旦点排序完毕,它们就会形成一条简单的闭合路径(见下图)。 

第二阶段(接受或拒绝点):

    一旦我们有了闭合路径,下一步就是遍历该路径并移除该路径上的凹点。如何决定移除哪个点以及保留哪个点?同样,方向在这里有帮助。排序数组中的前两个点始终是凸包的一部分。对于剩余的点,我们跟踪最近的三个点,并找到它们形成的角度。让这三个点分别为prev(p)、curr(c)和next(n)。如果这些点的方向(按相同顺序考虑它们)不是逆时针的,我们丢弃 c,否则我们保留它。下图显示了此阶段的分步过程。
 

下面是上述算法的实现: 

// A C++ program to find convex hull of a set of points. Refer
//c++ https://blog.csdn.net/hefeng_aspnet/article/details/141713859
//java https://blog.csdn.net/hefeng_aspnet/article/details/141717851
//python https://blog.csdn.net/hefeng_aspnet/article/details/141717981
//C# https://blog.csdn.net/hefeng_aspnet/article/details/141718039
//Javascript https://blog.csdn.net/hefeng_aspnet/article/details/141718097
// for explanation of orientation()
#include <iostream>
#include <stack>
#include <stdlib.h>
using namespace std;

struct Point
{
    int x, y;
};

// A global point needed for  sorting points with reference
// to  the first point Used in compare function of qsort()
Point p0;

// A utility function to find next to top in a stack
Point nextToTop(stack<Point> &S)
{
    Point p = S.top();
    S.pop();
    Point res = S.top();
    S.push(p);
    return res;
}

// A utility function to swap two points
void swap(Point &p1, Point &p2)
{
    Point temp = p1;
    p1 = p2;
    p2 = temp;
}

// A utility function to return square of distance
// between p1 and p2
int distSq(Point p1, Point p2)
{
    return (p1.x - p2.x)*(p1.x - p2.x) +
          (p1.y - p2.y)*(p1.y - p2.y);
}

// To find orientation of ordered triplet (p, q, r).
// The function returns following values
// 0 --> p, q and r are collinear
// 1 --> Clockwise
// 2 --> Counterclockwise
int orientation(Point p, Point q, Point r)
{
    int val = (q.y - p.y) * (r.x - q.x) -
              (q.x - p.x) * (r.y - q.y);

    if (val == 0) return 0;  // collinear
    return (val > 0)? 1: 2; // clock or counterclock wise
}

// A function used by library function qsort() to sort an array of
// points with respect to the first point
int compare(const void *vp1, const void *vp2)
{
   Point *p1 = (Point *)vp1;
   Point *p2 = (Point *)vp2;

   // Find orientation
   int o = orientation(p0, *p1, *p2);
   if (o == 0)
     return (distSq(p0, *p2) >= distSq(p0, *p1))? -1 : 1;

   return (o == 2)? -1: 1;
}

// Prints convex hull of a set of n points.
void convexHull(Point points[], int n)
{
   // Find the bottommost point
   int ymin = points[0].y, min = 0;
   for (int i = 1; i < n; i++)
   {
     int y = points[i].y;

     // Pick the bottom-most or choose the left
     // most point in case of tie
     if ((y < ymin) || (ymin == y &&
         points[i].x < points[min].x))
        ymin = points[i].y, min = i;
   }

   // Place the bottom-most point at first position
   swap(points[0], points[min]);

   // Sort n-1 points with respect to the first point.
   // A point p1 comes before p2 in sorted output if p2
   // has larger polar angle (in counterclockwise
   // direction) than p1
   p0 = points[0];
   qsort(&points[1], n-1, sizeof(Point), compare);

   // If two or more points make same angle with p0,
   // Remove all but the one that is farthest from p0
   // Remember that, in above sorting, our criteria was
   // to keep the farthest point at the end when more than
   // one points have same angle.
   int m = 1; // Initialize size of modified array
   for (int i=1; i<n; i++)
   {
       // Keep removing i while angle of i and i+1 is same
       // with respect to p0
       while (i < n-1 && orientation(p0, points[i],
                                    points[i+1]) == 0)
          i++;


       points[m] = points[i];
       m++;  // Update size of modified array
   }

   // If modified array of points has less than 3 points,
   // convex hull is not possible
   if (m < 3) return;

   // Create an empty stack and push first three points
   // to it.
   stack<Point> S;
   S.push(points[0]);
   S.push(points[1]);
   S.push(points[2]);

   // Process remaining n-3 points
   for (int i = 3; i < m; i++)
   {
      // Keep removing top while the angle formed by
      // points next-to-top, top, and points[i] makes
      // a non-left turn
      while (S.size()>1 && orientation(nextToTop(S), S.top(), points[i]) != 2)
         S.pop();
      S.push(points[i]);
   }

   // Now stack has the output points, print contents of stack
   while (!S.empty())
   {
       Point p = S.top();
       cout << "(" << p.x << ", " << p.y <<")" << endl;
       S.pop();
   }
}

// Driver program to test above functions
int main()
{
    Point points[] = {{0, 3}, {1, 1}, {2, 2}, {4, 4},
                      {0, 0}, {1, 2}, {3, 1}, {3, 3}};
    int n = sizeof(points)/sizeof(points[0]);
    convexHull(points, n);
    return 0;
}

输出: 

(0,3)
(4,4)
(3,1)
(0,0)

时间复杂度: O(nLogn),其中 n 为输入点的数量。

    第一步(找到最底部的点)需要 O(n) 时间。第二步(对点进行排序)需要 O(nLogn) 时间。第三步需要 O(n) 时间。在第三步中,每个元素最多被推送和弹出一次。因此,第六步逐个处理点需要 O(n) 时间,假设堆栈操作需要 O(1) 时间。总体复杂度为 O(n) + O(nLogn) + O(n) + O(n),即 O(nLogn)。

辅助空间: O(n),因为使用了显式堆栈,所以没有占用额外的空间。

凸包的应用:

    凸包的应用范围很广,包括:

    碰撞检测:凸包可用于快速确定两个物体是否发生碰撞。这在计算机图形学和物理模拟中很有用。

    图像处理:凸包可用于分割图像中的对象。这对于诸如对象识别和跟踪之类的任务很有用。

    计算几何:凸包用于各种计算几何算法,例如查找最近的点对和计算一组点的直径。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2183606.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Australis 相機率定軟體說明

概要 課堂中使用Australis這套軟體&#xff0c;順帶記錄操作過程 內容以老師口述及我測試的經過 照片為老師課堂提供之 說明 執行 Step1. 匯入照片 注意&#xff01;&#xff01;如果是Mac的作業系統&#xff0c;將資料夾移到Windows上的時候&#xff0c;建議創一個新的資料…

mysql---索引类型及索引方法使用

mysql索引类型 Normal、Full Text、Unique 在 MySQL 中&#xff0c;索引的类型主要有以下几种&#xff1a; Normal Index&#xff08;普通索引&#xff09;&#xff1a; 这是最基本的索引类型&#xff0c;没有唯一性要求。允许重复值&#xff0c;可以加速查询性能。用法&#…

产品经理的学习

初学 接需求 画原型 写文档 日常产出 流程图 举例购物的流程 结构图 一个应用的全部功能&#xff0c;用思维导图的方式去罗列出来 竞品分析文档 竞品分类 竞品选择 竞品采集 竞品文档书写 也可以做一个产品的产品结构图 需求文档 干系人 需求方 记录人 产品经理 其他项目干系人…

搭建企业级私有仓库harbor

华子目录 harbor简介实验环境准备下载软件包安装docker-cehosts解析 实验步骤配置https加密传输解压进入解压目录&#xff0c;修改文件配置启动harbor 测试客户端配置harbor本地加速器注意 通过docker compose管理harbor harbor简介 harbor是由wmware公司开源的企业级docker r…

LLM基础概念:Token

什么是token&#xff1f;为什么要限制token的输入&#xff1f;平时说的消耗token数指的是什么&#xff1f; token是用于自然语言处理的词的片段。 在自然语言处理模型中&#xff0c;限制token数量主要是出于计算效率和资源限制的考虑。每一个token都对应一个向量&#xff0c;…

Linux gadget 模拟触控屏 支持多点触控

通过gadget命令行生成hid设备 下面xxx自己根据需要修改&#xff0c;例如VID,PID&#xff0c;产品名称 const char *INSTALL_GADGET_CMDS[] {"modprobe libcomposite","mkdir /sys/kernel/config/usb_gadget/g1","echo xxx > /sys/kernel/config/…

github项目--crawl4ai

github项目--crawl4ai 输出html输出markdown格式输出结构化数据与BeautifulSoup的对比 crawl4ai github上这个项目&#xff0c;没记错的话&#xff0c;昨天涨了3000多的star&#xff0c;今天又新增2000star。一款抓取和解析工具&#xff0c;简单写个demo感受下 这里我们使用cra…

衡水中学资料大全-重构版(状元、学霸笔记)

文章目录 一、衡水中学&#xff1a;教育界的璀璨明珠二、状元笔记&#xff1a;学霸的智慧传承三、学霸笔记&#xff1a;高效学习的秘籍四、全面复习资料&#xff1a;覆盖所有考点五、思维导图&#xff1a;构建知识框架六、获取方式 一、衡水中学&#xff1a;教育界的璀璨明珠 …

【React】入门Day01 —— 从基础概念到实战应用

目录 一、React 概述 二、开发环境创建 三、JSX 基础 四、React 的事件绑定 五、React 组件基础使用 六、组件状态管理 - useState 七、组件的基础样式处理 快速入门 – React 中文文档 一、React 概述 React 是什么 由 Meta 公司开发&#xff0c;是用于构建 Web 和原生…

语音转文字免费利器:助力高效办公与学习

语音转文字免费的软件如同一股清流&#xff0c;让我们能够更轻松地将语音信息转化为可编辑的文字内容。今天我们一起来分析它们的功能、特点以及如何为我们的生活和工作带来便利。 1.365在线转文字 链接直达&#xff1a;https://www.pdf365.cn/ 这是一个功能强大的在线工具…

网站集群批量管理-密钥认证与Ansible模块

一、集群批量管理-密钥认证 1、概述 管理更加轻松&#xff1a;两个节点,通过密钥形式进行访问,不需要输入密码,仅支持单向. 服务要求(应用场景)&#xff1a; 一些服务在使用前要求我们做秘钥认证.手动写批量管理脚本. 名字: 密钥认证,免密码登录,双机互信. 2、原理 税钥对…

MySQL 的复制延迟:理解与解决方案

一、什么是 MySQL 的复制延迟&#xff1f; 在 MySQL 数据库中&#xff0c;复制是一种将数据从一个数据库服务器&#xff08;主服务器&#xff09;复制到一个或多个数据库服务器&#xff08;从服务器&#xff09;的机制。复制延迟指的是主服务器上的数据更改与这些更改在从服务…

DBeaver显示PostgreSQL数据库的信息模式

DBeaver连接PostgreSQL数据库后&#xff0c;默认情况下是不加载信息模式的&#xff0c;如果有需要&#xff0c;我们可以通过设置显示信息模式。 具体步骤&#xff1a;点击数据库连接–>右键打开设置–>连接设置–>常规–>导航视图–>自定义–>勾选显示系统对…

Python 基于 flask 的前程无忧招聘可视化系统,Python大数据招聘爬虫可视化分析

博主介绍&#xff1a;✌程序员徐师兄、7年大厂程序员经历。全网粉丝12w、csdn博客专家、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专栏推荐订阅&#x1f447;…

springboot的调度服务与异步服务实操

1.调度服务 1.1.JDK之ScheduledExecutorService 讲到调度任务&#xff0c;我们脑海里马上会想到ScheduledExecutorService。 ScheduledExecutorService是 Java java.util.concurrent 包中的一个接口&#xff0c;它继承自 ExecutorService 接口。它主要用于在给定的延迟后运行…

计算机毕业设计Python+Spark知识图谱微博舆情预测 微博推荐系统 微博可视化 微博数据分析 微博大数据 微博爬虫 Hadoop 大数据毕业设计

《PythonSpark知识图谱微博舆情预测》开题报告 一、课题背景与意义 随着互联网技术的飞速发展&#xff0c;社交媒体平台如微博已成为人们表达观点、交流信息的重要渠道。微博每天产生海量的数据&#xff0c;这些数据中蕴含着丰富的社会情绪、事件动态等信息&#xff0c;对于政…

从概念到使用全面了解Llama 3 这个迄今为止最强大的开源模型

概述 mate最近发布了 Llama3&#xff0c;下一代最先进的开源大语言模型&#xff08;LLM&#xff09;。正如本文的综合评论所述&#xff0c;Llama 3 以其前身奠定的基础为基础&#xff0c;旨在增强 Llama 2 成为 ChatGPT 重要开源竞争对手的能力 Llama 2&#xff1a;深入探讨 C…

【更新】红色文化之红色博物馆数据集(经纬度+地址)

数据简介&#xff1a;红色博物馆作为国家红色文化传承与爱国主义教育的重要基地&#xff0c;遍布全国各地&#xff0c;承载着丰富的革命历史与文化记忆。本数据说明旨在汇总并分析全国范围内具有代表性的红色博物馆的基本信息&#xff0c;包括其地址、特色及教育意义&#xff0…

Scrapy框架入门

一、Scrapy简介 Scrapy是一款快速而强大的web爬虫框架&#xff0c;基于Twisted的异步处理框架、Twisted是事件驱动的。 Scrapy是由python实现的爬虫框架&#xff1a;架构清晰、可扩展性强、可以灵活完成需求。 一、Scrapy应用 scrapy及其他模块的安装 pip3 install scrapy…

【Java编程系列】使用java接入Microsoft Graph,实现发送邮件功能

1、前言 微软与2022年10月1号&#xff0c;开始停止了部分服务的 basic auth &#xff08;账密登录&#xff09;功能&#xff0c;需要改用 oauth2.0 协议接入相应服务。邮件方面主要在于IMAP和pop协议。并且与2023年1月1日时&#xff0c;正式全面停止账密登录使用去接入上述服务…