Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python:在以边列表表示的图形中查找连接的组件_Python_Algorithm_Search_Graph_Networkx - Fatal编程技术网

Python:在以边列表表示的图形中查找连接的组件

Python:在以边列表表示的图形中查找连接的组件,python,algorithm,search,graph,networkx,Python,Algorithm,Search,Graph,Networkx,我在表格中有一个边缘列表 start | end a c b d e b 我有几千万条边(大约3000万条),我无法将整个图形读入内存-至少不能使用networkx这样的库,因为它有点内存密集 我的目标是在该列表所表示的图中找到包含少于x个节点的所有连接组件 例如,我希望获得节点数小于x=30的所有连接组件。但我不想通过构建整个图然后搜索连接的组件(例如,调用此networkx命令:nx.connected\u component\u子图(nxg))来

我在表格中有一个边缘列表

start | end
 a       c
 b       d
 e       b
我有几千万条边(大约3000万条),我无法将整个图形读入内存-至少不能使用networkx这样的库,因为它有点内存密集

我的目标是在该列表所表示的图中找到包含少于
x
个节点的所有连接组件

例如,我希望获得节点数小于
x=30
的所有连接组件。但我不想通过构建整个图然后搜索连接的组件(例如,调用此networkx命令:
nx.connected\u component\u子图(nxg)
)来实现这一点

是否有一种方法可以只使用边缘列表文件搜索连接的组件,而不必构建整个图形


附加信息:节点名称是长度为10-20 asci值的字符串。

首先需要为节点分配较短的标识符,以减少数据占用空间。您可以将这些较短的标识符和原始名称之间的映射写入另一个文件,以便在运行算法后将任何解决方案转换为这些名称

假设您有足够短的节点标识符,您可以将内存中的所有内容加载到由节点标识符键入的字典中

然后使用Union Find结构和算法来识别连接的组件

最后,按允许的最大大小过滤这些内容

有一些库提供了unionfind实现,可以提供更好的性能。下面是Union Find的一个简单实现:

class Node:
    def __init__(self, key):
        self.key = key
        self.parent = self
        self.size = 1

class UnionFind(dict):
    def find(self, key):
        node = self.get(key, None)
        if node is None:
            node = self[key] = Node(key)
        else:
            while node.parent != node: 
                # walk up & perform path compression
                node.parent, node = node.parent.parent, node.parent
        return node

    def union(self, key_a, key_b):
        node_a = self.find(key_a)
        node_b = self.find(key_b)
        if node_a != node_b:  # disjoint? -> join!
            if node_a.size < node_b.size:
                node_a.parent = node_b
                node_b.size += node_a.size
            else:
                node_b.parent = node_a
                node_a.size += node_b.size
此演示的输出为:

[['i', 'e', 'a', 'u', 'o'], ['g', 'r', 'm', 'h'], ['k', 's', 'v']]

你的节点名有多长?假设它们被编码为整数,那么它们的数组只需要大约500 MB。我将使用pandas将文件读取为csv,将第一列设置为排序索引,并从头开始实现广度优先搜索。通过巧妙地使用loc,这可能会变得非常迅速。我正在使用pandas来读取文件。但节点名称是长度为10-20 asci值的字符串。我会用这些信息更新帖子。你有没有从边缘列表中搜索CCs的代码示例@Alexnet重要的信息是,你可以把所有的东西都放进记忆中。如果第一列是索引,我相信在while循环中使用df.loc[第二列]可以相对容易地实现广度优先搜索。如果我以后有时间,我会写一个原型。这太完美了,谢谢
data = """x d
c j
i e
f x
n z
a u
g r
w x
p l
u o
m g
k s
t q
y l
h m
n b
k v
e u
i o
r m
n c
x q
f q
j l
s v"""

results = find_components(data.splitlines(), 5)
print(results)
[['i', 'e', 'a', 'u', 'o'], ['g', 'r', 'm', 'h'], ['k', 's', 'v']]