《常见算法和数据结构》元素排序(4)——凸包问题

元素排序(4)——凸包问题


本系列文章主要介绍常用的算法和数据结构的知识,记录的是《Algorithms I/II》课程的内容,采用的是“算法(第4版)”这本红宝书作为学习教材的,语言是java。这本书的名气我不用多说吧?豆瓣评分9.4,我自己也认为是极好的学习算法的书籍。

通过这系列文章,可以加深对数据结构和基本算法的理解(个人认为比学校讲的清晰多了),并加深对java的理解。

凸包问题

凸包问题就是说,找到一个最小的凸多边形能圈住所有的点。

这里写图片描述

凸包问题的应用

  • 运动规划:找到从s到t的最短路径,最短路径肯定在凸包上

这里写图片描述

  • 最远的一对:相隔最远的点对肯定在凸包上

Alt text

凸包的几何性质

  • 可以通过逆时针遍历所有凸包顶点
  • 凸包的顶点是关于p的极角的递增序列,而p有最小的y坐标。

这里写图片描述

Graham 扫描算法

  1. 选择y坐标最小的p
    • 如何确定最小y坐标?
      循环一遍
  2. 对所有的点按关于p的 极角排序
    • 如何对点进行极角排序?
    • 如何效率的排序?
      用MergeSort
  3. 按顺序连接每个点,如果发现打破 pi2pi1pi 打破了逆时针的原则,则舍弃 pi1,pi

    • 如何判断是否打破了逆时针原则ccw?
    • 如何解决退化问题(多个点在一条直线上)

      通过计算(b-a)和(c-a)的叉乘就行了。
      如果area > 0 则是逆时针,
      如果area < 0 则是顺时针
      如果area = 0 则是共线

这里写图片描述

代码

由于每次要判断最后的2个点是否是逆时针,毫无疑问使用栈结构是比较合适的

public class Point2D 
{
   private final double x;
   private final double y;
   public Point2D(double x, double y)
   {
      this.x = x;
      this.y = y;
   } 
   ...
   public static int ccw(Point2D a, Point2D b, Point2D c)
   {
      double area2 = (b.x-a.x)*(c.y-a.y) - (b.y-a.y)*(c.x-a.x);
      if      (area2 < 0) return -1;  
// clockwise
      else if (area2 > 0) return +1;  
// counter-clockwise
      else                return  0;  
// collinear
   }
}
stack<Point2D> hull = new Stack<Point>();
Array.sort(p,Point2D.Y_ORDER);//find p
Array.sort(p,p[0],BY_POLAR_ORDER)//

hull.push(p[0]);
hull.push(p[1]);

for(i = 2;i < N;i++)
{
    Point2D top = hull.pop();
    while(Point2D.ccw(hull.peek(),top,p[i]) <= 0)
        top = hull.pop();
    hull.push(top);
    hull.push(p[i]);

}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值