凸壳算法

 凸壳算法在模式识别、图像处理、图形学和人工智能方面有着广泛的应用,很多问题都可以归纳为凸壳问题求解。

可能我以后用到的比较少,就当是普及算法了,以下简单介绍凸壳串行算法。

关于凸壳的串行算法,可以说有好多种,有时间复杂度O(n^2)的,也有O(nlogn)的,下面依次介绍几种算法:

1、卷包裹法,时间复杂度为O(n^2)

由Chand 和 Kapur 于1970年提出,基本思想:首先过y坐标最小的点p1画一条水平直线L,显然该点是凸壳的一个顶点。然后L绕p1按逆时针方向旋转,碰到S(顶点集合)中的第二个点p2时,直线绕p2按逆时针旋转而在p1,p2之间留下一条线,该线段为凸壳的一条边。继续旋转下去,最后直线L旋转360度回到p1,便得到所求的凸壳

直线L绕点pi旋转式通过一下方法实现的:首先连接Pi与非凸壳顶点Pj,j = i+1,...,n,得到线段PiPj,然后求这些线段与L(线段Pi-1Pi)的夹角,组成最小夹角的另一端点Pi+1就是凸壳顶点

这个很显然时间复杂度为O(n^2),伪代码在此就省略了!

注意一点:就是当有三点或者以上的点共线时,如果只能算两个端点上的点,中间的其他点不计,在算法执行中要另外判断,当最小角度有好几个的时候,要选一个距离最远的一个点

2,最优的求凸壳算法:格雷厄姆方法

  1972年,格雷厄姆发表的一篇题为"An efficient algorithm for determining the convex hull of a finite planar set"的著名论文中所提出的方法

  • 8
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
凸壳(Convex Hull)算法是计算几何中的一类基本问题,它的目标是找到一个点集的最小凸多边形。Java实现凸壳算法的思路大致如下: 1. 首先,我们需要定义一个点的数据结构来存储点的坐标信息。可以使用Java中的Point2D类或者自定义一个Point类。 2. 然后,我们需要找到点集中最左边的点,将其作为凸壳的起点。 3. 接着,我们需要按照极角排序将剩余的点按照与起点的极角从小到大排序。 4. 然后,我们可以开始构建凸壳。我们可以使用一个栈来维护凸壳的点集。首先将起点和极角最小的点入栈。 5. 对于剩余的点,我们需要判断它是否在凸壳的内部。如果在内部,则将栈顶元素出栈,直到该点不在凸壳内部为止。 6. 最后,将该点入栈。 7. 重复步骤5和6,直到所有点都被处理完毕。 8. 最后,栈中的点集就是凸壳的点集。 下面是Java代码示例: ```java import java.util.*; public class ConvexHull { // 定义点的数据结构 static class Point { double x; double y; public Point(double x, double y) { this.x = x; this.y = y; } } public static List<Point> convexHull(List<Point> points) { // 找到最左边的点,作为凸壳的起点 Point start = points.get(0); for (Point p : points) { if (p.x < start.x) { start = p; } } // 按照极角排序 Collections.sort(points, new Comparator<Point>() { @Override public int compare(Point p1, Point p2) { double angle1 = Math.atan2(p1.y - start.y, p1.x - start.x); double angle2 = Math.atan2(p2.y - start.y, p2.x - start.x); if (angle1 < angle2) { return -1; } else if (angle1 > angle2) { return 1; } else { return 0; } } }); // 构建凸壳 Stack<Point> stack = new Stack<>(); stack.push(start); for (int i = 1; i < points.size(); i++) { Point p = points.get(i); while (stack.size() >= 2) { Point top = stack.pop(); Point secondTop = stack.peek(); if ((p.x - secondTop.x) * (top.y - secondTop.y) - (p.y - secondTop.y) * (top.x - secondTop.x) >= 0) { stack.push(top); break; } } stack.push(p); } // 将栈中的点集转换为List返回 List<Point> result = new ArrayList<>(); while (!stack.isEmpty()) { result.add(stack.pop()); } Collections.reverse(result); return result; } public static void main(String[] args) { List<Point> points = new ArrayList<>(); points.add(new Point(0, 0)); points.add(new Point(0, 1)); points.add(new Point(1, 1)); points.add(new Point(1, 0)); points.add(new Point(0.5, 0.5)); List<Point> hull = convexHull(points); for (Point p : hull) { System.out.println(p.x + " " + p.y); } } } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值