凸包问题 —— Graham扫描法

凸包问题(Graham扫描法) /** 凸包问题 —— Graham扫描法: 找出点集p[]中最下面的点(有多个时取最左边的),以该点为极点,求出其他所有点的极角, 显然,极角范围为 [0, 180)度,对这些点按极角的升序排序,也就是按极角的余切值降序排列, 先把极点和排序后的第一个点和第二个点入栈,再一次循环(i = 3 -> n-1),若栈顶的两个点和 当前的点p[i]这三点连线的方向向顺时针方向偏转,则栈顶元素出 阅读详情
 凸包问题 —— Graham扫描法:

(1)找出点集p[]中最左下的点p1,把p1同点集中其他各点用线段连接,并计算这些线段与水平线的夹角,然后按夹角从小到大和按到p1的距离从近到远排序(夹角范围为 [0, 180)度,而且可以删除相同夹角且距离p1较近的点,保留最远点,这样可减少计算量。因为直线上的非端点不是凸包的极点,即如果p1,p2,p3在一条直线上,则只取凸点p1,p3。p2不在端点,故可以去掉),得到新的节点序列p1,p2,...pn.依次连接这些点,得到一个多边形(已经逆时针,有所进展,但还需去掉不在凸包上的点)。此时p1是凸包的边界起点,p2和pn也是最终凸包的顶点,p[n+1]=p1(看成循环的)

(2)删除p3,p4,...p[n-1]中不在凸包上的点:

先把p1,p2,p3入栈S中,再依次循环(i = 3 -> n-1),若栈顶的两个点和当前的点p[i]这三点连线的方向向顺时针方向偏转,表明是凹的,应删除,则栈顶元素出栈(要循环判断,即可能前面的仍是凹的,还需再出栈,举例如下图),直到向逆时针方向偏转或者栈内只有2个元素了(p1p2),就把当前点p[i]入栈。

最后栈中的元素就是最终凸包上的点。

分析:一般会从最左下点p1开始,根据所有点斜率中最小的求下一个凸包点pa,再根据pa的所有点斜率中最小的来求下一个凸包点pb,依此类推,但这样就是三重循环(p1,pa,pb是一次,p1,pa,pb内部的排序有2次,共三重循环),这样效率不高(其实这就是卷包裹法,复杂度为O(NH),其中N是全部的点数 H是最终在凸包上的点数)。Graham扫描法只取所有点对p1的斜率,后面的点充分利用该斜率的信息,并作某些处理,进行改进,以提高效率。这是由多到少,由多个到1个的方法,并充分利用已知条件。

下面图例也可说明栈扫描的过程(摘自http://www.cnblogs.com/Booble/archive/2011/03/10/1980089.html#2065991):

----------------

--------------- 

--------------------

以下截图代码摘自《ACM程序设计培训教程 吴昊 中国铁道出版社》 :

―――――――――――

下面为网上转载:

对于一个有三个或以上点的点集Q,Graham扫描法的过程如下:

  令p0为Q中Y-X坐标排序下最小的点
  设<p1,p2,...pm>为对其余点按以p0为中心的极角逆时针排序所得的点集(如果有多个点有相同的极角,除了距p0最远的点外全部移除
  压p0进栈S
  压p1进栈S
  压p2进栈S
    for i ← 3 to m
      do while 由S的栈顶元素的下一个元素、S的栈顶元素以及pi构成的折线段不拐向左侧
        对S弹栈
      压pi进栈S
    return S;
若计算周长。将边相加               zoj1453
若计算面积。穷举三点构成的三角形。。找最大zoj2419

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#define MaxNode 100015
int stack[MaxNode];
int top;
typedef struct POINT
{
    int x;
    int y;
}POINT;
POINT point[MaxNode];
void swap(POINT point[],int i,int j)
{
    POINT tmp;
    tmp=point[i];
    point[i]=point[j];
    point[j]=tmp;
}
double multi(POINT p1,POINT p2,POINT p0) //叉乘
{
    return ((p1.x-p0.x)*(p2.y-p0.y)-(p1.y-p0.y)*(p2.x-p0.x));
}
double distence(POINT p1,POINT p2) //p1,p2的距离
{
    return sqrt((p1.x-p2.x)*(p1.x-p2.x)+(p1.y-p2.y)*(p1.y-p2.y));
}
int cmp(const void *a,const void *b)
{
    POINT *c=(POINT *)a;
    POINT *d=(POINT *)b;
    double k=multi(*c,*d,point[0]);
    if(k<0) return 1;
    else if(k==0&&distence(*c,point[0])>=distence(*d,point[0])) return 1; //极角相同,比距离
    else return -1;
}
void grahamscan(int n)
{
    int i,u;
    u=0;
    for(i = 1;i<= n-1;i++) //找到最左下的点p0
        if((point[i].y < point[u].y)||(point[i].y==point[u].y&&point[i].x < point[u].x))
            u=i;
    swap(point,0,u);
    qsort(point+1,n-1,sizeof(point[0]),cmp); //按极角排序
    for(i = 0;i <= 2;i++) stack[i] = i; //p0,p1,p2入栈
    top=2;
    for(i = 3;i <= n-1;i++) //最终凸包的各顶点的编号依次存在stack[]中。
    {
        while(multi(point[i],point[stack[top]],point[stack[top-1]])>=0) //弹出非左转的点
     {
            if(top==0)break;
            top--;
    }
        top++;
        stack[top] = i;
    }
}
//求凸包的面积
double polygonArea(int n,POINT p[])
{
    double area;
    int i;
    area = 0;
    for(i = 1;i <= n;i++){
        area += (p[stack[i - 1]].x * p[stack[i % n]].y - p[stack[i % n]].x * p[stack[i - 1]].y);
    }
    return fabs(area) / 2;
}

int main()
{
    int i;
    for(i=0;i<10;i++)
        scanf("%d%d",&(point[i].x),&(point[i].y));
    grahamscan(10);
    printf("%lf\n",polygonArea(10,point));
}

 

Graham扫描法解凸包问题 本篇是继续上篇的凸包问题的解法——将采用Graham扫描法来解凸包问题 我们再上一篇说到用分治法去解决凸包问题的最坏时间复杂度是O(n^2)。 那么利用Graham扫描法解决凸包问题可以降到O(nlogn)的量 Graham扫描法 我们可以采用一个贪心法的策略来解凸包问题 什么是贪心算法 我们区别于动态规划算法的那种从整体考虑部分,加以选择,而是从某种意义或者一些普遍真理的一种量度去达到局部的最优... 阅读详情

相关推荐

[HDU 1293][简论计算几何问题中的常用二维凸包问题的算法][Graham扫描法][Andrew扫描法]

&lt;font face="Consolas"&gt;## 简论计算几何问题中的常用二维凸包问题的算法### &gt;0 HDU 1293 Surround the Trees 先来一段例题压压惊.. Surround the Trees Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K ...

qq_34840328的博客 516

凸包算法理解——基于MATLAB代码

凸包算法;扫描式;matlab代码;

Fang_good的博客 1513

Matlab二维凸包计算

其中,X和Y是列向量,表示点的x和y坐标。函数将返回一个polyshape对象P,它表示一个封闭的多边形,以及一个列向量K,它包含独立的凸包顶点的索引值,这些顶点按照逆时针顺序排列。其中,X和Y是列向量,表示点的x和y坐标。除了使用convhull和boundary函数外,我们还可以使用Matlab中的polyshape函数来计算二维凸包。运行程序后,会显示带有随机点云和计算出的凸包的图像。运行程序后,会显示带有随机点云和计算出的凸包的图像。运行程序后,会显示带有随机点云和计算出的凸包的图像。

DevProPlus的博客 1272

Graham扫描法求解二维凸包问题

问题定义 (文章内容来源于算法导论) 点集QQQ的凸包是一个最小的凸多边形PPP,满足QQQ中的每个点都在PPP的边界上或者在PPP的内部。现给定一个点集,求解其凸包(即构成凸包的点集)。 Graham扫描法 Graham扫描法可以以O(nlogn)O(nlogn)O(nlogn)时间复杂度求解凸包问题,其中nnn为点集大小。以下是算法的伪代码: 令p0为Q中具有最小纵坐标的点(或等价地,具有最小横坐标的点); 令<p1,p2,...,pm>为 ......

Castria的博客 1741

Matlab:计算凸包

Matlab:计算凸包

希望我的博客,能帮上你解决学习中工作中所遇到的问题 1687

MATLAB:求凸包算法

凸包是计算几何中的一个基础问题,它是指在平面上给定n个点,找到这些点的最小凸多边形,该多边形包含所有的n个点。求解凸包的算法有很多种,其中比较常用的有 Graham 扫描算法和 Jarvis 步进算法。每加入一个点后,判断新的三个点组成的折线是否为“左拐弯”(即逆时针转);Jarvis 步进算法是另一种凸包算法,其基本思想是从平面上的一个点开始,每次找到与当前凸包最外围相邻的点,并加入凸包之中。Graham 扫描算法是一种经典的凸包算法,其基本思想是将平面上的点按照极角排序,然后依次将点加入凸包之中。

CyberGenius的博客 858

凸包问题 --- 蛮力法,Graham扫描法

凸包问题 --- 蛮力法,Graham扫描法问题描述蛮力法 问题描述 给定一个平面上n个点的集合,它的凸包就是包含所有这些点的最小凸多边形,求取满足此条件的所有点。 另外,形象生动的描述: (1)我们可以把这个问题看作如何用长度最短的栅栏把n头熟睡的老虎围起来。 (2)也可以这样看:请把所讨论的点想象成钉在胶合板上的钉子,胶合板代表平面。撑开一根橡皮筋圈,把所有的钉子都围住,然后啪一声松开手。凸包...

来日浅谈的博客 2554

MATLAB实现的二维凸包算法:二元分类应用详解

凸包算法是一种用于计算一组数据点的最小凸多边形的数学工具。在计算机科学和统计学中,凸包被广泛应用在诸如图像处理、路径规划、数据分析等领域。从几何学角度来讲,凸包就是包含所有数据点的最小凸多边形,即任何点的连线都不应超出这个多边形。在实际应用中,凸包可以用来识别数据点的分布范围,进而辅助进行进一步的数据处理和分析。二元分类问题是机器学习中的一个基础问题,它指的是将数据样本划分为两个互斥类别中的一个。这类问题广泛存在于诸如垃圾邮件检测、医疗诊断、信用评分等实际场景中。

weixin_31715353的博客 799

Graham扫描法求解凸包问题(C++)

目录 凸包概念 算法思路 算法过程 1、准备数据 2、数据处理 2.1 获取左下角的点 2.2 坐标点移动至左下角点坐标系中 2.3 坐标点排序 3、Graham算法 3.1 判断点与线(栈顶点和原点连线)的关系 3.2 计算夹角(顺逆时针旋转) 3.3.算法主体 执行结果 凸包概念 1 点集Q的凸包(convex hull)是指一个最小凸多边形,满足Q中的点或者在多边形边上或者在其内。图1中由红色表示线段的多边形就是点集Q={p0,p1,...p12}的凸包。 2 一组..

qq_45929977的博客 3247

凸包实现 Matlab 代码:此代码实现了凸包算法。-matlab开发

有关更多信息和理解代码,请访问: http://codesmesh.com/convex-hull-matlab-code-and-explanation/

react-window 大数据列表和表格数据渲染组件之虚拟滚动

ReactWindow是一个高性能的React虚拟滚动组件库,专门用于高效渲染大型列表和表格数据。它通过“窗口化”技术,仅渲染用户可见区域的内容,大幅提升性能并减少内存消耗。主要特点包括:支持固定/可变大小列表项、多种布局类型(垂直/水平/网格)、轻量级设计(不足5KB)以及平滑的滚动体验。相比传统渲染方式,它能轻松处理成千上万条数据,并提供自动滚动、自适应容器大小等高级功能。与同类库相比,ReactWindow具有更简洁的API和更优的性能表现,是处理大数据量渲染场景的理想选择。

前端开发-前端技术分享 1136

python 三维凸包_凸包问题,Graham扫描法,python实现

凸包问题是指在n个点中,寻找一个凸多边形,使所有的点在凸多边形的边界或者内部。这是一个很有意思的计算机图形学问题,一种常用的解法是Graham扫描法,运行时间为O(nlgn)。笔者拿processing语言对整个算法过程进行了模拟,上动态图: 注意processing拿左上为(0,0)原点,与一般数学的原点位置不同。从动态图上可以看出整个算法分三个部分:1、寻找y轴最小的点,如果y轴位置是相同的,...

weixin_39924179的博客 1003

科研人必备!用WisPaper搭建个人文献知识库的完整指南(附Zotero联动技巧)

本文详细介绍了如何利用WisPaper搭建高效的个人文献知识库,包括文件命名标准化、文件夹结构设计、语义搜索技巧及与Zotero的深度联动方法。通过智能标签系统和知识图谱功能,科研人员可以快速定位关键文献,提升研究效率。特别适合需要管理大量学术文献的研究者。

weixin_30823001的博客 267

Graham扫描法:轻松掌握2D凸包问题的优雅解法

凸包是计算几何中的基础概念,指包含给定点集的最小凸多边形,广泛应用于计算机视觉、路径规划和碰撞检测等领域。Graham扫描法是计算凸包的经典算法,通过四个步骤实现:寻找基点、极角排序、栈扫描构建凸包以及处理退化情况。其核心在于利用向量叉积判断点的位置关系,时间复杂度为O(nlogn)。尽管算法高效,但在处理高维数据和大规模点时存在局限性,需结合其他方法优化。文章还提供了Python代码实现和学习资源推荐,帮助读者深入理解并应用该算法。

weixin_68733376的博客 2187

华为P812E光猫补全shell配置PON口模式

终于看到华为企业级的带2.5电口P812E横空出世了,相信很多发烧友也已经将此收入昂中。相信体验的同时,遇到的第一件事情就是配置PON口模式的问题,本文将带发烧基友解锁模式。

GUAIYU的博客 5727

华为防火墙双线路配置实战:5分钟搞定主备自动切换(含健康检查避坑指南)

本文详细介绍了华为防火墙双线路配置实战,包括主备自动切换和健康检查机制的优化技巧。通过智能健康检查机制,华为防火墙能实现毫秒级故障自动切换,确保网络高可用性。文章提供了从架构设计到实战配置的全流程指南,并分享了常见配置误区与解决方案,帮助中小企业快速搭建稳定可靠的网络架构。

weixin_30872337的博客 604

凸包问题——Graham扫描法

查看原文:http://www.wyblog.cn/2016/12/01/%e5%87%b8%e5%8c%85%e9%97%ae%e9%a2%98-graham%e6%89%ab%e6%8f%8f%e6%b3%95/首先明白什么是凸包? 点集Q的凸包是指一个存在的最小凸多边形,满足Q中的所有点或者在多边形边上或者在其内。 求解凸包问题有几种方法,这里介绍最常用的Graham扫描法,并给出代

wy的点滴 1933

stm32cubeMX使用HAL库点亮LED流水灯

目录

weixin_46129506的博客 3797

HDU 1397——Surround the Trees(凸包问题,graham扫描法)

Surround the Trees Problem Description There are a lot of trees in an area. A peasant wants to buy a rope to surround all these trees. So at first he must know the minimal required length of the rope. However, he does not know how to calculate it. Can yo

qq_52282880的博客 666

WS2812呼吸灯效果实战:用STM32的PWM+DMA实现流畅渐变(附完整代码)

本文详细介绍了如何使用STM32的PWM+DMA技术实现WS2812呼吸灯效果,提供完整的代码示例和调试技巧。通过PWM波形编码和DMA传输机制,解决了传统IO模拟控制方式的高CPU占用问题,实现了流畅的LED渐变效果,适用于各种嵌入式开发场景。

weixin_30566063的博客 452

华为海思IC前端中后端(COT&XPU)岗位笔试机考题

华为海思COT和XPU部门IC前端,IC中端,IC后端岗位笔试真题分享

weixin_37584728的博客 3362

凸包问题 --- 蛮力法,Graham扫描法

问题描述 蛮力法 Graham扫描法 问题描述 给定一个平面上n个点的集合,它的凸包就是包含所有这些点的最小凸多边形,求取满足此条件的所有点。 另外,形象生动的描述: (1)我们可以把这个问题看作如何用长度最短的栅栏把n头熟睡的老虎围起来。 (2)也可以这样看:请把所讨论的点想象成钉在胶合板上的钉子,胶合板代表平面。撑开一根橡皮筋圈,把所有的钉子都围住,然后啪一声松开手。凸包就是以橡皮圈...

serena_0916的博客 873

基于深度学习的生活垃圾检测与分类系统:YOLOv5、YOLOv6、YOLOv7与YOLOv8实现

本项目的目标是开发一个基于YOLO系列模型的生活垃圾检测与分类系统。数据集准备与标注:收集并标注生活垃圾图像数据集。模型训练:使用YOLOv5、YOLOv6、YOLOv7、YOLOv8等深度学习模型训练垃圾分类系统。UI界面设计:设计一个简洁的用户界面,支持图像或视频的上传与垃圾分类结果展示。实时垃圾检测与分类:通过摄像头进行实时垃圾检测和分类。结果展示与保存:展示检测结果,支持用户保存分类后的图像或视频。

YOLO 705
上一篇: 《编程之美》两链表相交及扩展详解
下一篇: 凸包2:分治法解决凸包问题
tmljs1988
博客等级 码龄19年 134粉丝 107原创
评论 3
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值