我想在无向图中找到连接的组件。但是,我没有邻接矩阵。相反,我有一组顶点以及一个告诉我两个顶点是否相邻的函数。查找所有已连接组件的最有效方法是什么?
我知道我可以只计算整个邻接矩阵并使用深度优先搜索来找到所有组件。但这不是很有效,因为我需要检查每对顶点。
我当前正在执行以下步骤:
这是伪代码:
connected_components(vertices):
// vertices belonging to the current component and whose neighbors have not yet been added
vertices_to_check= [vertices.pop()]
// vertices belonging to the current component
current_component = []
components = []
while (vertices.notEmpty() or vertices_to_check.notEmpty()):
if (vertices_to_check.isEmpty()): // All vertices in the current component have been found
components.add(current_component)
current_component = []
vertices_to_check= [vertices.pop()]
next_vertex = vertices_to_check.pop()
current_component.add(next_vertex)
for vertex in vertices: // Find all neighbors of next_vertex
if (vertices_adjacent(vertex, next_vertex)):
vertices.remove(vertex)
vertices_to_check.add(vertex)
components.add(current_component)
return components
我知道,在大多数情况下,此方法比计算邻接矩阵要快,因为如果已知两个顶点属于同一分量,则不需要检查两个顶点是否相邻。但是有办法改进这种算法吗?
答案 0 :(得分:2)
最终,任何算法都必须为原来属于单独组件的每对顶点调用vertices_adjacent
,因为否则它将无法验证这些组件之间没有链接。
现在,如果大多数顶点都属于单个分量,则可能不会有太多这样的对;但是除非您期望大多数顶点都属于单个分量,否则没有专门针对这种情况进行优化的意义。因此,放弃这种情况,最好的情况是:
vertices_adjacent
。。 。 。这仍然涉及使¼| V | 2 + || V | − 2次调用vertices_adjacent
。相比之下,构建邻接表方法使½| V | 2 -½| V |调用-比最佳情况要大,但要小于2。(最糟糕的情况仅相当于“建立邻接表”方法。)如果没有一个分量包含两个以上的顶点,或者该图是非循环的,并且您不太可能选择要首先检查的边,则将发生这种情况。大多数图将位于两者之间。)
因此,对于精确调用vertices_adjacent
的最小次数精确而言,可能不值得进行过于紧密的优化。
也就是说,您的方法对我来说似乎很合理;它不会对vertices_adjacent
进行任何不必要的调用,因此,如果可以更好地猜测哪些调用对消除以后的调用很有用,那么唯一的改进就是提高概率。 / p>
一种可能性:根据power-law distribution,在许多图中,有些顶点有很多邻居,而有些顶点却很少。因此,如果根据已知的顶点数确定顶点的优先级,则可以利用该模式。 (我认为,如果大多数顶点确实确实都属于单个分量,那么这特别有用,这是唯一的优于2的改进甚至是可以想象。)但是,您必须测试一下,看看它是否真的对您感兴趣的图表有所影响。