📅  最后修改于: 2023-12-03 15:22:37.246000             🧑  作者: Mango
凸包是计算几何中的一个重要问题,它求得是一个点集最小凸多边形的顶点集合。而单调链算法则是求解凸包的一种重要算法。
凸包可以使用暴力枚举和 Graham-Scan 等算法实现,但是单调链算法是比较高效的一种方法。它的原理如下:
首先对点集按照 x 坐标进行排序;
分别求出从左到右和从右到左的两个单调链;
将这两个单调链合并成一个。
对于单调链的求解,分别有两个单调栈:
左单调栈:从左到右不断向栈中添加点,保证栈中点纵坐标单调递增;
右单调栈:从右到左不断向栈中添加点,保证栈中点纵坐标单调递减。
下面是单调链算法的具体实现:
def monotonic_chain(points):
# 对点按照 x 坐标排序
points.sort()
# 从左到右的单调栈
left_stk = []
for pt in points:
while len(left_stk) >= 2 and (left_stk[-1] - left_stk[-2]).cross(pt - left_stk[-2]) < 0:
left_stk.pop()
left_stk.append(pt)
# 从右到左的单调栈
right_stk = []
for pt in reversed(points):
while len(right_stk) >= 2 and (right_stk[-1] - right_stk[-2]).cross(pt - right_stk[-2]) < 0:
right_stk.pop()
right_stk.append(pt)
# 合并两个单调链
return left_stk[:-1] + right_stk[:-1]
其中 cross
函数即向量叉积,定义如下:
class Vec2:
# vector2 class
...
def cross(self, other):
return self.x * other.y - self.y * other.x
使用单调链算法求解凸包可以得到一个点集的最小凸包顶点集合。
下面是一个例子:
points = [Vec2(0, 3), Vec2(2, 2), Vec2(1, 1), Vec2(2, 1),
Vec2(3, 0), Vec2(0, 0), Vec2(3, 3)]
hull_pts = monotonic_chain(points)
hull_pts
将得到点集的最小凸包顶点集合。
在计算几何中,凸包问题很重要,而单调链算法是其中的一种高效算法。实际上,在计算几何中还有其他的算法,例如 Graham-Scan、QuickHull、Chan 等,不仅效率高,而且更加通用,可以处理各种凸包问题。