迭代测试二维网格连通性的算法

时间:2018-08-07 22:17:55

标签: algorithm language-agnostic flood-fill

假设我有一个2D网格大小,每个索引可以容纳零或一。网格开始时会充满零,然后逐渐添加零。在每一步中,我想验证添加下一个元素是否不会阻止零形成一个连接的组件(使用具有北,东,南和西邻居的4连通网格)。

什么是快速算法来迭代测试2D网格的连通性?

当前,我在每次迭代中都使用泛洪填充,但是我觉得应该有一个使用先前迭代中的信息的更快算法。

另外,即使它们没有断开网格,放置它们的方法有时也会取消放置它们的位置,因此我正在寻找的算法需要能够处理该问题。 / p>

1 个答案:

答案 0 :(得分:2)

这受Kruskal迷宫生成算法的启发。

我将正方形的邻域定义为8个周围的正方形,包括网格的外部(角落正方形的邻域是3个周围的正方形加上外部,所以总共有4个“正方形”)。

将1放入集合中,以便任何两个相邻的1属于同一集合。将网格的外部视为一个大的1(这意味着第一个集合包含它)。添加1时,只需检查其邻居即可。

下面是所有可能的情况。为了便于查看,我将从1开始对集合编号,并使用集合编号代替包含1的每个正方形中的1。外部属于编号为1的集合。您也可以使用它来简化实施。方括号表示新放置的1。

如果新的1没有相邻的1,则它属于新的集合。

 0 0 0 0 0
 0 2 0 0 0
 0 0 0[3]0
 0 0 0 0 0
 0 0 1 0 0

如果它有一个相邻的1,则它属于同一集合。

 0 0 0 0 0
 0 2 0 0 0
 0 0[2]0 0
 0 0 0 0 0
 0 0 1 0 0

如果它具有多个相邻的1,并且属于同一集合的所有邻居都是直接邻居,则可以合并这些集合,而新的1属于结果集合。您无需检查是否断开连接。

 0 0 0 0 0                0 0 0 0 0
 0 2 0 0 0                0 1 0 0 0
 0 0[3]1 0       ->       0 0[1]1 0
 0 0 1 1 0                0 0 1 1 0
 0 0 1 0 0                0 0 1 0 0

 0 0 0 0 0                0 0 0 0 0
 0 2 0 0 0                0 1 0 0 0
 0 2 0 1 0       ->       0 1 0 1 0
[3]0 0 1 0               [1]0 0 1 0
 1 1 1 0 0                1 1 1 0 0

如果它具有多个相同集合的相邻1,但它们并非全都是直接邻居,则您断开连接。

 0 0 0 0 0                0 0 0 0 0 <- first group of 0s
 0 2 0 0 0                0 1 0 0 0
 0 0[3]1 0       ->       0 0[1]1 0
 0 1 0 1 1                0 1 0 1 1
 1 0 0 0 0                1 0 0 0 0 <- second group of 0s

 0 0 0 0 0 <- first group of 0s
 0 0 1 0 0
 0 1 0 1 1 
[1]1 0 0 0
 0 0 0 0 0 <- second group of 0s

 0 0 0 0 0                0 0 0 0 0
 0 2 0 0 0                0 1 0 0 0
 0 2 0 1 0       ->       0 1 0 1 0
[3]0 0 1 0               [1]0 0 1 0
 0{1}1 0 0      lone 0 -> 0{1}1 0 0

在最后一个示例中,标记为{1}的1和外部在技术上是邻居,但从新放置的1的角度来看不是这样。

在一般情况下,当删除具有多个相邻1的1时,您需要检查在删除之后它们是否仍然连接(例如,通过在它们之间运行探路器)。如果没有,请将它们分成不同的集合。

如果您知道0都已连接,则可以在本地进行检查:如果其邻居都是直接邻居,则删除1不会拆分它所属的集(但是请小心外部)。它将在附近是否存在多个“空白”。

在特殊情况下,您仅以相反的顺序删除1,就可以跟踪哪些新添加的1加入了多个集合(如果需要,甚至包括当时的集合)。稍后将其删除时,它们将拆分它们的集合。