凸包Graham Scan算法实现

凸包算法实现点集合中搜索凸包顶点的功能,可以处理共线情况,可以输出共线点也可以不输出而只输出凸包顶点。经典的Graham Scan算法,点排序使用极角排序方式,并对共线情况做特殊处理。一般算法是将共线的点去掉距离小的,保留最远的,这样处理会导致不能输出凸包边上的点,只能输出顶点。但是有时候需要输出这些边上的点,因此这里我将共线点都保留,并按照顺序排列。共线点排列方式是:非起始边按照从远道近排列,起始边按从近到远排列。

实现如下:#include <iostream>
#include <math.h>
using namespace std;
typedef struct{double x,y;} Point;
void qsortpoint(Point s[],Point base,int start,int end);
void sortstartedge(Point s[],int nums);
//向量(x1,y1),(x2,y2)的叉积
double CrossMul(double x1,double y1,double x2,double y2)
{return x1*y2-x2*y1;
}
//向量(x1,y1),(x2,y2)的点积
double DotMul(double x1,double y1,double x2,double y2)
{return x1*x2+y1*y2;
}
//跨立判断
//判断点c是在向量ab的逆时针方向还是顺时针方向,大于零逆时针,等于0则共线
double CrossMul(Point a,Point b,Point c)
{return CrossMul(b.x-a.x,b.y-a.y,c.x-a.x,c.y-a.y);
}
//计算向量ab和ac点积
double DotMul(Point a,Point b,Point c)
{return DotMul(b.x-a.x,b.y-a.y,c.x-a.x,c.y-a.y);
}
//判断浮点数符号
int doublecmp(double d)
{if(fabs(d)<10e-6)return 0;return d>0?1:-1;
}
//判断同一直线上的三个点位置,点c是否在点ab之间
bool betweenCmp(Point a,Point b,Point c)
{if(doublecmp(DotMul(c,a,b))<=0)return true;return false;
}
//判断j是否在base->i向量的左边或当共线时j是否位于它们的线段之间
bool isLeftorNearer(Point base,Point i,Point j)
{if(CrossMul(base,i,j)>0)return true;if(CrossMul(base,i,j)==0 && betweenCmp(base,i,j))return true;return false;
}
void swap(Point& a,Point& b)
{Point temp = b;b=a;a=temp;
}
//以s中的最低点为参考点,对其他所有点进行极角排序(逆时针)
//共线时离参考点较远的点排在前面,凸包的起始边共线点从近到远排列
void sortpoint(Point s[],int nums)
{//找最低点for(int i=1;i<nums;i++){if(s[i].y<s[0].y || (s[i].y==s[0].y && s[i].x<s[0].x))swap(s[0],s[i]);}qsortpoint(s,s[0],1,nums);//将起始边上的共线点重新排列sortstartedge(s,nums);
}
void sortstartedge(Point s[],int nums)
{int i,j;for(i=2;i<nums;i++){if(CrossMul(s[0],s[1],s[i])!=0)break;}for(j=1;j<(i+1)/2;j++)swap(s[j],s[i-j]);
}//将点按极角逆时针排序
void qsortpoint(Point s[],Point base,int start,int end)
{if(start>=end)return;Point partition = s[end-1];int i=start-1,j=start-1;while(++j<end-1){if(isLeftorNearer(base,s[j],partition)){swap(s[++i],s[j]);}}swap(s[++i],s[end-1]);qsortpoint(s,base,start,i);qsortpoint(s,base,i+1,end);
}
void ConvexHull(Point s[],int nums,Point result[],int& resultnums)
{sortpoint(s,nums);resultnums = 0;if(nums<=3){for(int i=0;i<nums;i++)result[resultnums++] = s[i];return;}int top=0;int i;for(i=0;i<2;i++)result[top++] = s[i];while(i<nums){//用<号判断则包含凸包边上的共线点,<=号判断则只包含凸包顶点if(CrossMul(result[top-2],result[top-1],s[i])<=0){top--;}else{result[top++] = s[i++];}}//最后加入起点形成闭包while(CrossMul(result[top-2],result[top-1],s[0])<=0){top--;}result[top++]=s[0];resultnums = top;
}
int main()
{Point pa[] = {{0,0},{1,0},{2,0},{3,0},{4,0},{4,1},{4,2},{4,3},{4,4},{3,4},{2,4},{1,4},{0,4},{0,3},{0,2},{0,1},{2,2},{1,1}};cout<<"convex hull is:"<<endl;Point result[18];int nums;ConvexHull(pa,18,result,nums);for(int i=0;i<nums;i++)cout<<result[i].x <<"," <<result[i].y<<endl;return 0;
}
经验证,算法无误。

凸包Graham Scan算法实现相关推荐

  1. graham算法 java_凸包Graham Scan算法实现

    凸包算法实现点集合中搜索凸包顶点的功能,可以处理共线情况,可以输出共线点也可以不输出而只输出凸包顶点.经典的Graham Scan算法,点排序使用极角排序方式,并对共线情况做特殊处理.一般算法是将共线 ...

  2. 计算几何入门 1.6:凸包的构造——Graham Scan算法

    上文简要分析出了凸包构造问题算法的下界:O(nlogn),在此就引入一种下界意义上最优的算法:Graham Scan算法.这种算法可以保证在最坏情况下时间复杂度也不超过nlogn.我们先大致了解一下算 ...

  3. 计算几何--凸包之graham scan算法

    Graham scan算法主要步骤: 找出所有已知点的y值最小,如果相同,取x值最小的点,作为基准点s. 以s为基准,所有的点按照与X轴夹角从小到大排序. 使用两个栈,一个记录已访问的点,一个记录未访 ...

  4. Graham Scan算法

    预备知识:凸集:集合S中任意两点的连线都在集合S中,如果简单的理解,可以理解为凸边形 凸包:对于给定集合X,所有包含X的凸集的交集,简单的理解,就是包含X的最小凸集,或者就是最外圈的点连起来 极角排序 ...

  5. Graham Scan凸包算法

    获得凸包的算法可以算是计算几何中最基础的算法之一了.寻找凸包的算法有很多种,Graham Scan算法是一种十分简单高效的二维凸包算法,能够在O(nlogn)的时间内找到凸包. 首先介绍一下二维向量的 ...

  6. HDUOJ 1392凸包graham算法

    #include <iostream> #include <cstdio> #include <cstring> #include <cmath> #i ...

  7. Python:实现graham scan葛立恒扫描法算法(附完整源码)

    Python:实现graham scan葛立恒扫描法算法 from __future__ import annotations from collections import deque from e ...

  8. 凸包Graham算法

    在学习Graham算法前,需要先了解二维叉乘这个概念. 叉乘的拓展 在一般的常识或者教科书中规定叉乘只有3d才拥有,其实2d也可以拓展出来一个叉乘形式,而且非常有用. 拓展方式:假设有两个2d向量a, ...

  9. HDU 5928 DP 凸包graham

    给出点集,和不大于L长的绳子,问能包裹住的最多点数. 考虑每个点都作为左下角的起点跑一遍极角序求凸包,求的过程中用DP记录当前以j为当前末端为结束的的最小长度,其中一维作为背包的是凸包内侧点的数量.也 ...

最新文章

  1. R语言使用gt包和gtExtras包优雅地、漂亮地显示表格数据:使用gtExtras包添加一个图,显示表中某一列中的数字、并自定义表格数据显示的主题格式、并自定义数值数据的格式(例如百分比)
  2. python sizeof函数_C++ sizeof 运算符 | 菜鸟教程
  3. 阿里云ecs禁止ping,禁止telnet
  4. oracle的oradata,Oracle使用oradata恢复数据库
  5. Sublime Text3自定义快捷键
  6. 信息学奥赛一本通 2072:【例2.15】歌手大奖赛
  7. php 设置 server 变量,php 服务器变量 $_SERVER
  8. error C2065: 'assert' : undeclared identifier
  9. 导数与微分的知识点思维导图_高中物理思维导图,高中三年知识点一个不漏
  10. word保存不了磁盘已满_【Word技巧】word使用终极技巧,工程人必会(二)
  11. 过去式加ed的发音_过去式,过去分词,加ed 后的读法
  12. 复合函数的极限与连续
  13. win10 机械硬盘 开机速度缓慢的原因排查与优化
  14. 手机chrome没有声音_Chrome浏览器没有声音,解决windows10Chrome浏览器没有声音的问题...
  15. tiny4412编译出来的zImage不能开机
  16. 【windows8开发】开发平台与开发框架
  17. 电影评论情感分析-直播案例
  18. catia中画螺杆 螺纹
  19. csgo服务器响应参数,csgo必备弹道参数 影响弹道参数设置
  20. 源码篇-2048小游戏(需要EasyX图形库)

热门文章

  1. 【设计模式】面向对象 - 多态 ( 面向对象 3 要素 | 多态 提升 程序扩展性 | 多态示例 )
  2. 【错误记录】Android 应用运行报错 ( You need to use a Theme.AppCompat theme (or descendant) with this activity. )
  3. 【FFmpeg】FFmpeg 相关术语简介 二
  4. 【数据挖掘】数据挖掘总结 ( K-Means 聚类算法 | 二维数据的 K-Means 聚类 ) ★
  5. 微信小程序打开PDF
  6. 【译】最大限度地降低多线程 C# 代码的复杂性
  7. 006-1MOS管工作原理精讲
  8. 2017-2018-1 20155207 《信息安全系统设计基础》第四周学习总结
  9. mongodb first
  10. javaSocket与C通信