📜  凸包|设置1(贾维斯算法或包装)(1)

📅  最后修改于: 2023-12-03 15:36:49.799000             🧑  作者: Mango

凸包 | 设置1(贾维斯算法或包装)

凸包(convex hull)是由一组点构成的最小凸多边形,包含所有给定点。凸包是许多计算几何问题的基础。

凸包问题可以用许多算法来解决,而其中贾维斯算法和包装算法是比较常见、易于实现的算法之一。

贾维斯算法 (Javis Algorithm)

贾维斯算法(也被称为公式法或左转法)是一种简单但低效的算法。它的基本思想是从点集中选中最左端的点,然后每次向左转去连接下一个点,直到构建出整个凸包。时间复杂度为 O(nh),其中 n 是给定点集的大小,h 是凸包中的点数。

伪代码如下:

定义函数jarvis(points):  
    p = 最左边的点  
    result = {}  
    i = 0  
    repeat:  
        result.add(p)  
        endpoint = points[0]  
        for j from 1 to n:  
            if (points[j] == p) or (endpoint == p) or (cross_product(p, endpoint, points[j]) > 0):   
                endpoint = points[j]  
        p = endpoint   
        i = i+1  
    until endpoint == result[0]  
    return result

其中,cross_product(p, q, r)表示向量pq和pr之间的叉积。如果向量pr在向量pq的左边,则叉积结果为正;在右边则为负。

贾维斯算法的优点是实现简单、易于理解。但是,它的时间复杂度较高,特别是当点集中有很多共线点时。

包装算法 (Graham's Scan Algorithm)

包装算法(Graham's Scan Algorithm)是一种改进的凸包算法,它的时间复杂度为O(nlogn)。

其基本思想是:首先找到一个最低点(即y坐标最小的点),然后将点集按照到该点的极角升序排序(如果极角相同,则按照距离目标点近的优先),最后依次将点加入凸包中。

伪代码如下:

定义函数graham_scan(points):  
    # 找到最低点  
    first_point = lowest_point(points)  
    # 将点集按照极角排序    
    sorted_points = sort_by_polar_angle(points, first_point)  
    # 依次将点加入凸包中  
    hull = []  
    for p in sorted_points:  
        while len(hull) > 1 and orientation(hull[-2], hull[-1], p) <= 0:  
            hull.pop()  
        hull.append(p)  
    return hull 

其中,orientation(p, q, r)表示向量pq和pr之间的方向。如果向量pr在向量pq的左边,则方向结果为正;在右边则为负。

包装算法的优点是时间复杂度较低,适用于处理大型数据集。

参考资料
  1. https://en.wikipedia.org/wiki/Convex_hull_algorithms
  2. https://www.geeksforgeeks.org/convex-hull-set-1-jarviss-algorithm-or-wrapping/
  3. https://www.geeksforgeeks.org/convex-hull-set-2-graham-scan/
  4. Computational Geometry: Algorithms and Applications (M. de Berg, et al.)