我需要解决动态凸包算法问题,即保持2D点的凸包,我可以添加和删除点。
天真的做法显然是O(N)
;每当添加/删除N
个点之一时,我们就会从头开始重新计算凸包。但是,我无法承受线性时间,因此我正在寻找一种次线性算法。到目前为止,我已经找到了一堆纸,所有这些都描述了一些具有疯狂时间限制的复杂算法,这需要花费很长时间才能实现。即使是最古老的高效算法,由于Overmars和Leeuween,O(log^2 N)
似乎太复杂了。 (像往常一样,这些论文中描述的大多数算法在结构/算法方面都有很多依赖性来自其他参考文献)
我正在寻找更简单,更不一定新颖的东西,在最坏的情况下表现优于线性(例如O(sqrt N)
)。最后,我不介意时间是否摊销。有什么想法吗?
(简单来说,我主要指的是不需要超过几百行代码的东西。)
答案 0 :(得分:8)
我认为你所追求的并不存在。 Overmars和vanLeeuwen算法并不复杂,在某种意义上似乎是必要的。首先,将问题改为分别维护上船体和下船体。其次,通过分而治之来构建每个,但保留中间树结构,以便你知道1/2套,1/4套等的船体。现在,当你删除一个点时,你只重新计算树中的祖先。当你添加一个点时,你会发现它加入了哪个叶子,并再次向上重新计算到根。
我认为如果你忽略了他们论文中的细节,只是按照这个高级草图,并以最无意识的方式实现所有步骤,它将不会复杂,并且将是次线性的。
微米。 H. Overmars和J. van Leeuwen。 维护飞机中的配置。 学家COMPUT。 SYST。 Sci。,23:166-204,1981。
答案 1 :(得分:2)
关于O'Rourke教授,他对计算几何学的了解远远超过我所知,我不知道OvL的“无意识”实现(即缺乏重新平衡的实现)如何可以是次线性的在最坏的情况下。
幸运的是,自1981年以来,我们在数据结构方面取得了一些进展。特别是,由于摊销保证就足够了,splay trees(1985)适合存储凸包和合并树。 Austern et al. (2003)提出了一种很好的方法来分离复杂平衡操作所需的额外字段的维护,因此您可以编写一次棘手的部分。
实现splay树的主要困难是splay操作,甚至比插入红黑树更简单。一旦splay工作,splay树 easy 就可以拆分和连接。要拆分,请展开要拆分的节点并剪切其正确的子节点。要加入,请展开第一个树的最右边节点,并使第二个树成为该节点的右子节点。
答案 2 :(得分:0)
我假设总共有N个数据点,复杂的船体由M点定义。
维护凸面船体比制造凸面船体要容易得多(而且价格便宜)。
删除现有数据点
1/ If the data point in not one of the M points defining the convex hull then it won’t affect the hull so just remove it.
2/ If it is part of the convex hull then you need to adjust the hull – more on that below in point 4
添加新数据点。
3/ If a data point is inside the complex hull then it will not affect the hull.
这是一个简单的方法来测试我的头脑。创建船体内部的三角剖分。使用M个点定义的复杂船体可以被三角化为M-2个三角形。然后测试该点是否位于其中一个三角形中。
4/ if a data point is outside the hull then it will become part of the hull. However, it is only affecting a local area of the hull and it is straightforward to find the new hull in a few steps. If you have already build the hull then it should be clear to you how to adjust a local part of it.
我看不出任何这种维护可以是O(N)