从集合中查找断开图的算法

时间:2017-06-16 19:46:43

标签: python algorithm graph

目标: 想要从大量集合中有效地查找所有断开连接的图表

例如, 我有一个如下数据文件:

helperObject

每个条目代表一组元素。 第一个条目A,B,C = {A,B,C} 这也表明A和B,A和C,B和C之间存在边缘。

我最初提出的算法如下

A, B, C
C, D, E
A, F, Z
G, J
...

上面的算法应该返回连接图的顶点列表。然而,由于数据集大小,我遇到了运行时问题。有大约100000个条目。 所以我只是想知道是否有人知道有更有效的方法来查找连接图。

数据结构也可以改成(如果这更容易) A,B 公元前 E,F ... 每个条目代表图形的边缘。

3 个答案:

答案 0 :(得分:5)

这看起来像是使用disjoint set data structure的理想情况。

这使您可以在几乎线性的时间内将集合连接在一起。

Python代码示例

from collections import defaultdict

data=["A","B","C"],["C","D","E"],["F","G"]

# Prepare mapping from data element to index
S = {}
for a in data:
    for x in a:
        if x not in S:
            S[x] = len(S)

N = len(S)
rank=[0]*N
parent=range(N)

def Find(x):
    """Find representative of connected component"""
    if  parent[x] != x:
        parent[x] = Find(parent[x])
    return parent[x]

def Union(x,y):
    """Merge sets containing elements x and y"""
    x = Find(x)
    y = Find(y)
    if x == y:
        return
    if rank[x]<rank[y]:
        parent[x] = y
    elif rank[x]>rank[y]:
        parent[y] = x
    else:
        parent[y] = x
        rank[x] += 1

# Merge all sets
for a in data:
    x = a[0]
    for y in a[1:]:
        Union(S[x],S[y])

# Report disconnected graphs
V=defaultdict(list)
for x in S:
    V[Find(S[x])].append(x)

print V.values()

打印

[['A', 'C', 'B', 'E', 'D'], ['G', 'F']]

答案 1 :(得分:2)

使用networkx这是一个专门用于以有效方式处理图形的模块:

import networkx as nx
sets = [{'A','B','C'}, {'C','D','E'}, {'F','G','H'}, ...]

创建图表并向其添加一些边缘:

G = nx.Graph()
for s in sets:
    l = list(s)
    G.add_edges_from(zip(l, l[1:]))

提取连接的组件(&#34;断开连接的图表&#34;在您的术语中):

print(list(nx.connected_components(G)))
# [{'D', 'C', 'E', 'B', 'A'}, {'F', 'H', 'G'}]

答案 2 :(得分:-2)

查看Rosetta Code任务Set consolidation

  

给定两组项目,如果任何项目对任何项目都是共同的那么   将合并应用于这些集合的结果是一组集合   内容是:

     

如果两个输入集之间不存在公共项,则两个输入集   的项目。单个集合是两个输入集的并集if   他们有一个共同的项目。

     

给定N组项目,其中N> 2,则结果与之相同   反复替换他们的两组的所有组合   合并,直到集合对之间没有进一步合并   可能。如果N <2,则合并没有严格的含义   输入可以返回。