在网络上关于凸包解法多种多样,讲的也非常的不错,可以参考一下这篇博客,但是还是想用自己的话去描述一遍,以加深一下印象。

常见的解法有:

  • 穷举法(蛮力法)
  • 分治法
  • Jarvis步进法
  • Graham扫描法
  • Melkman算法

本文主要讲一下Graham扫描法的步骤以及实现,先借一张动图来说明一下Graham扫描的算法的流程。

算法流程

  1. 找到相对左下角的点P0,为什么叫相对,因为我这里是先找到y轴最小的点,如果有相同,则选择X轴最小的点;
  2. 计算所有的点与P0的极角的大小,并由小到大的排序,如上面的动图所示排序好的顺序;
  3. 开始寻找凸包;
  • 第一步,P0和P1与P2去构建向量P0P1和P0P2,P1,P2,P3入栈
  • 第二步,P1和P2出栈,和P3构建向量P1P2,P1P3,所以P1和P3入栈
  • 第三步,以此类推,P1,P3出栈和P4构建向量,当向量的叉乘积大于0时,三者都进栈,否则中间点出栈,即P3出栈,两边点进栈(P1和P4进栈)

算法源码

1.寻找P0点

Point findPointMin(Point pointIn[], int size)
{Point pointOut = pointIn[0];for (int i = 1; i < size; i++){if (pointOut.y > pointIn[i].y){pointOut = pointIn[i];}else if (abs(pointOut.y - pointIn[i].y) < 0.000001){if (pointOut.x > pointIn[i].x){pointOut = pointIn[i];}}}return pointOut;
}

2.排序

bool sortPoint(Point a, Point b)
{bool stat = true;if (P0.x == a.x && P0.y == a.y)return true;if (P0.x == b.x && P0.y == b.y)return false;float angle_a = a.x == P0.x ? MAXFLOAT : (a.y - P0.y) / (a.x - P0.x);float angle_b = b.x == P0.x ? MAXFLOAT : (b.y - P0.y) / (b.x - P0.x);float length_a = (a.y - P0.y) * (a.y - P0.y) + (a.x - P0.x) * (a.x - P0.x);float length_b = (b.y - P0.y) * (b.y - P0.y) + (b.x - P0.x) * (b.x - P0.x);if (abs(angle_a - angle_b) <= 0.000001){stat = length_a > length_b ? false : true;}if (angle_a < 0 && angle_b >= 0){stat = false;}else if (angle_a >= 0 && angle_b < 0){stat = true;}else{if (angle_a < angle_b){stat = true;}else{stat = false;}}return stat;
}

3.寻找凸包

vector<Point> findConvexHull(Point pointIn[], int size)
{stack<Point> resultPoint;vector<Point> convexHull;queue<Point> tempPoint;float flag = 0;resultPoint.push(pointIn[0]);resultPoint.push(pointIn[1]);for (int i = 2; i < size; i++){// if(((pointIn[i-1].y - P0.y) * (pointIn[i].x - P0.x)) == (pointIn[i-1].x-P0.x) * (pointIn[i].y - P0.y))// {//    continue;// }Point p3 = pointIn[i];Point p2 = resultPoint.top();resultPoint.pop();Point p1 = resultPoint.top();flag = (p2.x - p1.x) * (p3.y - p1.y) - (p3.x - p1.x) * (p2.y - p1.y);if (flag > 0){resultPoint.push(p2);resultPoint.push(p3);}else if (flag == 0){resultPoint.push(p3);}else{while (1){p2 = resultPoint.top();resultPoint.pop();p1 = resultPoint.top();flag = (p2.x - p1.x) * (p3.y - p1.y) - (p3.x - p1.x) * (p2.y - p1.y);if (flag <= 0){resultPoint.push(p3);break;}else{resultPoint.push(p2);resultPoint.push(p3);break;}}}}cout << "result point" << endl;while (!resultPoint.empty()){Point temp = resultPoint.top();resultPoint.pop();cout << "(" << temp.x << "," << temp.y << ")" << endl;convexHull.push_back(temp);}return convexHull;
}

主函数

int main()
{vector<Point> convexHull;/* 测试数据*/// Point pointSet[10]={{1,2},{1,3},{0,3},{-1,3},{3,3},{4,3},{5,3},{-2,3},{6,3},{2,3}};// Point pointSet[10] = {{1, 0}, {2, 1}, {1, 3}, {2, 2}, {1, 2}, {3, 1}, {3, 3}, {3, 2}, {4, 1}};Point pointSet[10] = {{1, 0}, {1, 1}, {1, 3}, {2, 3}, {2, 2},{2,4}, {3, 3}, {3, 4}, {4, 3},{0,4}};/* 寻找P0*/P0 = findPointMin(pointSet, sizeof(pointSet) / sizeof(pointSet[0]));cout << "P0:" << P0.x << "  " << P0.y << endl;/* 按极角排序*/sort(pointSet, pointSet + 10, sortPoint);/* 寻找凸包*/convexHull = findConvexHull(pointSet, 10);
}

凸包算法-------Graham扫描法相关推荐

  1. 凸包算法Graham扫描法

    凸包算法(Graham扫描法) 转载自 SZUhg https://www.cnblogs.com/wpbing/p/9456240.html 叉乘与线段相交 判断一个点是否在一条线段的左边还是右边, ...

  2. Opencv 笔记7 凸包算法-Graham扫描法

    一.凸包 凸包(convex hull)是一个计算几何的概念,通俗的来说就是在一个二维的平面中有n 个点,我们可通过在外面的点画出一个多边型使得所以的点都在这个多边形里面,如下所示 二.Graham扫 ...

  3. 凸包(Graham扫描法构建)

    凸包(Graham扫描法构建) PS:我的妈呀,心态爆炸,好像也不太难,看各种模板看的云里雾里的,真的还是自己动手敲来的好,几乎没多久就懂的差不多了.... 一个本该寒假就该掌握的知识,居然熬了我几个 ...

  4. 凸包问题 —— Graham扫描法

    凸包问题 -- Graham扫描法: (1)找出点集p[]中最左下的点p1,把p1同点集中其他各点用线段连接,并计算这些线段与水平线的夹角,然后按夹角从小到大和按到p1的距离从近到远排序(夹角范围为 ...

  5. 凸包与Graham扫描法求凸包

    前置芝士 凸多边形 凸多边形指的是所有内角都在 (0,π](0,\pi](0,π] 范围内的多边形. 凸包 对于一个平面上的一个给定的点集,他们对应的凸包就是能把他们全部包含的最小凸多边形. 如果形象 ...

  6. 【opencv学习笔记】030 之 凸包之Graham扫描法与Jarvis步进法详解

    目录 一.前言 二.凸包 1.概念 2.凸包查找算法 1.Graham扫描法 2.Jarvis步进法 3.凸包API 4.代码展示 5.执行结果 一.前言 继续更新有关于opencv的基础博客,即将更 ...

  7. 寻找凸包的graham 扫描法

    1,点集Q的凸包(convex hull)是指一个最小凸多边形,满足Q中的点或者在多边形边上或者在其内.  2,凸包最常用的凸包算法是Graham扫描法和Jarvis步进法.  3,Graham扫描法 ...

  8. c语言凸包算法,基于C语言的凸包算法实现

    基于C语言的凸包算法实现 非计算机专业,代码有些的不好的地方,大佬轻喷^ _ ^ 根据要求,需要使用C语言实现凸包算法--Graham扫描法,本文将从算法理解.实现思路.遇到的问题及其解决方案三个方面 ...

  9. 转 最小凸包算法(Convex Hull)(1)-Graham扫描法 -计算几何-算法导论

    原文地址:http://blog.csdn.net/suwei19870312/article/details/542281 基本问题: 平面上有n个点p1,p2, ..., pn, 要求求出一个面积 ...

最新文章

  1. 大型云原生项目在数字化企业落地过程解密
  2. kali linux wps 2019 删除_一分钟,轻松上手 Linux 安装QQ,让你简单开启聊天办公新环境...
  3. mysql提示The server quit without updating PID file /usr/local/mysql/data/localhost.localdomain.pid
  4. jdbc配置文件连接mysql_java jdbc使用配置文件连接数据库:
  5. SAP中用json数据格式调用http接口发送短信邮件案例
  6. python django createsuperuser创建超级管理员命令
  7. 《追风行动》有点儿意思
  8. 课堂经验值管理小程序_微信小程序怎么管理门店?
  9. ContentProvider中的数据库的生成时机以及ContentResolver的insert()方法总结
  10. iOS可持续化集成: Jenkins + bundler + cocoapods + shenzhen + fastlane + pgyer
  11. 数学建模竞赛赛前准备及资源分享
  12. TypeScript-打包
  13. 路由器重温——ISIS路由-2
  14. Qt入门-QLabel类
  15. 开课吧-智能物联网训练营Day2-QT布局和植物与僵尸类构造
  16. 《孩子快抓紧妈妈的手 -----转载
  17. 阿里四面之后才懂得如何更好的学Java
  18. 巴士博弈_自主穿梭巴士内部和服务的设计
  19. 政务数据分级安全保护要求(明细)
  20. 申宝股票-抱团股继续杀跌

热门文章

  1. 分布式电商平台架构实践
  2. GPS观测值的线性组合
  3. chatgpt:栅格化原理和代码
  4. 洛谷 P4720 【模板】扩展卢卡斯定理/exLucas
  5. RS485通信学习笔记
  6. 微信之分享到朋友圈并记录分享次数
  7. poj1144 - tarjan求割点
  8. 【gym 101991 E】(ACPC 2018) E. Exciting Menus 题解
  9. 实体-关系图转换为关系模型
  10. 收藏!用Python一键批量将任意结构的CSV文件导入MySQL数据库。