📅  最后修改于: 2023-12-03 14:50:10.250000             🧑  作者: Mango
凸包是指包裹住一组点集中所有点的最小凸多边形。凸包可以应用于计算几何和图像处理等领域,例如:给定一组点,计算它们的闭包,或者通过它们找出最远点对等等。
凸包有两种算法,分别是朴素算法和单调链算法。在本文中我们将介绍单调链算法。
单调链算法是一种基于栈的算法,它的核心思想是:将点按照 x 坐标进行排序,然后分别求出上凸壳和下凸壳,再将两个凸壳合并,即可得到最终的凸包。
具体来说,我们假设点集为 P,将其按照 x 坐标排序。从左到右遍历这些点,对于每个点,我们都可以确定它在凸包中的位置:
下面是单调链算法的 C++ 实现代码:
// 用于比较两个点的大小
bool cmp(Point a, Point b) {
return a.x == b.x ? a.y < b.y : a.x < b.x;
}
// 判断三个点的向量关系
int crossProduct(Point A, Point B, Point C) {
return (B.x - A.x) * (C.y - A.y) - (C.x - A.x) * (B.y - A.y);
}
// 求解凸包
vector<Point> convexHull(vector<Point>& points) {
int n = points.size();
if (n <= 1) {
return points;
}
sort(points.begin(), points.end(), cmp);
vector<Point> ans;
// 求上凸壳
for (int i = 0; i < n; ++i) {
while (ans.size() >= 2 && crossProduct(ans[ans.size() - 2], ans.back(), points[i]) <= 0) {
ans.pop_back();
}
ans.push_back(points[i]);
}
// 求下凸壳
int m = ans.size();
for (int i = n - 2; i >= 0; --i) {
while (ans.size() >= m + 1 && crossProduct(ans[ans.size() - 2], ans.back(), points[i]) <= 0) {
ans.pop_back();
}
ans.push_back(points[i]);
}
return ans;
}
单调链算法的时间复杂度为 O(nlogn),其中 n 表示点的数量。这是因为算法的主要开销在于按照 x 坐标排序,以及遍历点集。
单调链算法是一种求解凸包的高效算法,它的时间复杂度为 O(nlogn),并且可以通过栈的数据结构方便地实现。在实际应用中,凸包可以帮助计算和识别出一组点集中的重要特征,如最远点对、最小覆盖圆等。