我很快就会遇到一个有趣的问题,我开始考虑算法了。我想的越多,我就越害怕,因为我认为它会变得非常可怕(O(n ^ 4)),除非我能变聪明。我很难搞清楚这个。这是对问题的简要描述。
我有N个多边形(其中N可以是巨大的> 10,000,000),它们被存储为M个顶点的列表(其中M大约为100)。我需要做的是为每个多边形创建一个由其他多边形共享的任何顶点的列表(将多边形视为周围感兴趣的区域,有时是区域,但相互对立)。我看到这样的东西
Polygon i | Vertex | Polygon j | Vertex
1 1 2 2
1 2 2 3
1 5 3 1
1 6 3 2
1 7 3 3
这意味着多边形1中的顶点1与多边形2中的顶点2相同,多边形1中的顶点2与多边形2中的顶点3相同。多边形1中的顶点5与顶点相同多边形3中的1 ....
为简单起见,我们可以假设多边形从不重叠,它们最接近的边缘是触及边缘,并且所有顶点都是整数(以使等式易于测试)。
我现在能做的唯一事情是每个多边形我必须遍历所有的多边形和顶点,这给我一个O(N ^ 2 * M ^ 2)的缩放,这将是非常糟糕的我的情况。我可以拥有非常大的多边形文件,所以我甚至无法将它全部存储在RAM中,因此这意味着要多次读取文件。
到目前为止,这是我的伪代码
for i=1 to N
Pi=Polygon(i)
for j = i+1 to N
Pj=Polygon(j)
for ii=1 to Pi.VertexCount()
Vi=Pi.Vertex(ii)
for jj=1 to Pj.VertexCount()
Vj=Pj.Vertex(jj)
if (Vi==Vj) AddToList(i,ii,j,jj)
end for
end for
end for
end for
我假设这已经出现在图形社区中(我没有花太多时间在那里,所以我不知道文献)。有任何想法吗?
答案 0 :(得分:4)
这是一个经典的迭代与内存问题。如果要将每个多边形与每个其他多边形进行比较,则会遇到O(n ^ 2)解。如果你在遍历所有多边形的过程中构建一个表,然后在表中行进,你会得到一个很好的O(2n)解决方案。我在采访中问了一个类似的问题。
假设你有可用的内存,你想创建一个多重图(一个键,多个条目),每个顶点作为键,多边形作为条目。然后,您可以将每个多边形精确地移动一次,将顶点和多边形插入到地图中。如果顶点已存在,则将多边形添加为该顶点键的附加条目。
一旦你击中了所有的多边形,你就可以遍历整个地图,并对任何有多个多边形条目的顶点做任何你想做的事。
答案 1 :(得分:2)
如果你有多边形/面数据,你甚至不需要查看顶点。
这为您提供了一个数组,用于描述每个顶点的使用次数。*
然后,您可以对多边形执行另一次传递并检查每个顶点的条目。如果是> 1你知道顶点是由另一个多边形共享的。
如果您需要存储/查找其他信息,可以进一步构建此策略。例如,您可以直接在数组中存储多边形而不是计数,从而可以获得使用给定顶点索引的所有面的列表。此时,您正在有效地创建一个顶点索引为关键的地图。
(*此示例假设您没有退化多边形,但可以轻松处理这些多边形。)
答案 2 :(得分:1)
嗯,一个简单的优化就是制作一个地图(可能是散列表),它将每个不同的顶点(由其坐标标识)映射到它所属的所有多边形的列表。这会将你的运行时间减少到类似于O(NM)的东西 - 仍然很大,但我怀疑你能做得更好,因为我无法想象有任何方法可以避免检查所有顶点。