c++多边形扫描线填充算法_凸包问题——Graham算法

cad3b5af0afdcec60d6859760139fad0.png

本篇文章将介绍二维的Graham扫描算法和它的源码实现。

Graham扫描算法会先将点按照极角的大小顺序排列,接着按顺序遍历每个点,通过夹角的大小判断哪些点在凸包上,算法的伪码如下所示:

求给定二维点集
的凸包
  1. 求出最左下角的点,即
    分量的值最小点,若
    分量值最小的点有多个,取
    分量最小的点,设为
    ;
  2. 剩下的点集,根据极角大小,逆时针排序,得到
    ;
  3. 令栈
    为空,用
    表示栈中第
    个元素,用
    表示栈中的元素个数;若栈中有
    个元素,则
    即为栈顶元素;每一次PUSH}操作,栈元素个数
    加1;每次POP操作,栈元素个数
    减1;
  4. PUSH(
    ,
    );
  5. PUSH(
    ,
    );
  6. for(
    ;
    ;
    )
  7.     while (
    && 由
    ,
    的夹角
    )
  8.         POP(
    );
  9.     end while;
  10. end for;
  11. if
    , then
  12.     点集无法生成一个凸包;
  13. else
  14.     栈
    中的
    个元素,就是凸包的顶点;
  15. end if;

1260809b5b0f3f1fa7ca9e5026a683bb.png
图1. Graham扫描算法过程

以如图1(a)所示为例,给定一个点集,

。第1步,选择最左下角的点
,若
分量值最小的点有多个,取
分量最小的点,特别注意,在实际实现中,可能存在多个相同的
点,必需把它们排除,保证点
是唯一的,否则在第2步中的排序会造成错误。第2步,如图(b)所示,对
按照极角从小到大进行排序,若极角相同,则根据与点
的距离从近到远排序。第3 ~ 5步,如图(c)所示,把
两个点压入栈中。逆时针方向处理每个顶点,第6 ~ 10步,如图(d)~(i),若
且由
,
的夹角大于等式180度,则把栈顶元素出栈,否则把新点
压入栈。最终得到的凸包如图(k)所示,点
在线段
上,是否把它作为凸包的顶点,可以根据具体的问题再作决定,上面提供的算法伪码,不允许把点
作为凸包的顶点。

对于对极点的排序,有多种算法实现,比如冒泡排序,快速排序,堆排序等,各种排序的性能对比,如表1的总结。若采用冒泡排序,则Graham扫描算法的复杂度将达到

,采用其它几种排序算法,Graham算法的复杂度都能达到
。采用快速排序,平均复杂度是
,在C++中,提供了qsort()快速排序的算法,但在最坏情况下,Graham算法的复杂度仍然是
。因此,可以选择归并排序或者堆排序。

22f7755025cabc411229df95fcb91723.png
表1. 有关排序算法的分析结果

基础库源码链接,参见这里,下面是前面所描述的算法的实现。

#include 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值