是否有用于查找复杂多边形的凸包的线性时间算法?

Posted

技术标签:

【中文标题】是否有用于查找复杂多边形的凸包的线性时间算法?【英文标题】:Is there a linear-time algorithm for finding the convex hull of a complex polygon? 【发布时间】:2011-03-23 11:22:46 【问题描述】:

我知道有一个最坏情况 O(n log n) 算法可以找到复杂多边形的凸包,还有一个最坏情况 O(n) 算法可以找到简单多边形的凸包。是否有最坏情况的 O(n) 算法来找到复杂多边形的凸包?

复杂多边形是线段可能相交的多边形。求一个复多边形的凸包,就相当于求一个无序列表的凸包。

【问题讨论】:

【参考方案1】:

我很确定不是。可以证明任意点集上的凸包等价于排序。我们可以对任意点集进行排序,然后将这些点按顺序连接成一个复杂的多边形,从而减少任意点集的问题。

这是一个指向proof 的链接,凸包相当于排序。我太懒了,打字员也太糟糕了,不能自己写出来。

【讨论】:

证明依赖于排序至少需要 O(n log n) 的想法。但是,这仅适用于基于比较的排序。由于点是整数或浮点数,因此我们可以使用比简单比较更多的操作。特别是,基数排序可以在 O(n) 时间内对点进行排序。【参考方案2】:

一般来说,不存在 O(n) 解决方案。有一个比 O(n log n) 更好的像素化版本。然而,它在其他方面是如此的笨拙,以至于你在实践中使用它会很疯狂。

您将第一个多边形(使用顶点 0、1、2)渲染到屏幕空间,然后使用不同的 ID 重新渲染顶点本身,以便以后可以识别它们。例如,您可以将帧缓冲区清除为 RGBA ffffffff 并将 fffffffe 用于凸包覆盖的空间。每个顶点将使用其 ID 作为其 RGBA 进行渲染; 00000000、00000001等

16 位示例:

fffffffffffffff
fffffff0fffffff
ffffffeeeffffff
fffffeeeeefffff
ffffeeeeeeeffff
fffeeeeeeeeefff
ff2eeeeeeeee1ff
fffffffffffffff

检查新点是在当前帧缓冲区中进行的简单查找。如果它占据的像素被多边形或顶点ID“着色”,则新顶点被拒绝。

如果新顶点在现有多边形之外,您会在新顶点和凸包内的某个点之间找到第一个像素(第一个多边形中间的某个点可以正常工作)并沿着包的圆周行进 -在两个方向上 - 直到你发现自己在新顶点的船体远端。 (我将把这个作为练习留给用户。从效率的角度来看,有很多解决方案都很糟糕。)填充由这两个点定义的多边形和带有多边形空间 ID 的新顶点 - 小心不要擦除任何顶点 ID - 并继续下一个像素。

完成后,任何包含顶点 ID 且未被外壳 ID 完全包围的像素都是凸外壳顶点。

虽然该算法的复杂度是 O(n) 与顶点的数量,但它的缺陷是显而易见的。 没有人会使用它,除非他们有一个荒谬、疯狂、惊人的点数要处理,这样几乎每个顶点都会被立即拒绝,除非他们可以接受别名结果的限制.

朋友不要让朋友实现这个算法。

【讨论】:

听起来当算法添加一个顶点时(它必须做 O(n) 次),它必须沿着船体的圆周行进到目前为止(这需要 O(n)时间)。这不是 O(n**2) 吗?也许我误解了算法。 不。圆周受帧缓冲区大小的限制,其遍历的复杂性不受其中顶点数量的影响——仅受其包含的像素数量的影响。跟踪具有 3 个顶点和 3,000,000 个顶点的相同大小的帧缓冲区需要相同的时间。 @user30997:我明白了。如果我们将帧缓冲区的大小(以像素 (p) 为单位)视为变量而不是常数,那么 n 和 p 的时间复杂度是多少? 如果 n 是顶点数并且帧缓冲区是 p 边上的像素,那么考虑到你可以对凸包的圆周进行的最长遍历是 2p,你有一个复杂性2np。 n 独立于 p,给出 O(n) 的 Big-O 时间复杂度。但是,每次操作的成本非常高,因此该算法仅对一小部分应用程序有用。这在算法中并不少见:例如,考虑一下“几乎排序”的列表,您知道没有一个项目与多于一个位置的位置不同。排序复杂度为 O(n)。【参考方案3】:

如果您的点集使得某些非基于比较的排序机制(如基数排序)比基于比较的方法更快,那么您似乎可以使用格雷厄姆扫描算法 (http://www.math.ucsd.edu/~ronspubs/72_10_convex_hull.pdf) 来计算它。 Graham 扫描的时间复杂度主要由排序步骤决定。其余的是线性的。

【讨论】:

【参考方案4】:

如果您的点来自有限宇宙(实践中总是如此),您可以进行基数排序,然后运行 ​​Andrew 的单调链算法。

【讨论】:

以上是关于是否有用于查找复杂多边形的凸包的线性时间算法?的主要内容,如果未能解决你的问题,请参考以下文章

亚线性但简单的动态凸壳算法?

半平面交

凸包算法

Python 查找算法_众里寻他千百度,蓦然回首那人却在灯火阑珊处(线性二分,分块插值查找算法)

[算法与数据结构] 谈谈线性查找法~

[算法与数据结构] 谈谈线性查找法~