编程语言
首页 > 编程语言> > python – 给定一个非循环有向图,返回一组“在同一级别”的节点集合?

python – 给定一个非循环有向图,返回一组“在同一级别”的节点集合?

作者:互联网

首先,我不确定这样的算法是什么,这是主要的问题 – 所以问题的第一部分是这个算法叫做什么?

基本上我有一个DiGraph(),我插入节点[1,2,3,4,5,6,7,8,9,10]和边缘([1,3],[2,3], [3,5],[4,5],[5,7],[6,7],[7,8],[7,9],[7,10])

从这里我想知道是否有可能获得如下收集:[[1,2,4,6],[3],[5],[7],[8,9,10]]

编辑:如果它有帮助,让我添加一些约束.
– 没有周期,这是有保证的
– 图表没有一个起点

我正在尝试做的是收集同一级别的节点,以便它们的处理可以并行化,但在外部集合中,处理是串行的.

EDIT2:很明显我没有想过这个,所以最简单的描述“级别”的方法是最深层的前任,所有节点都具有相同深度的前辈.因此,上面列表中的第一个条目是所有节点,其中0是最前面的,第二个有一个,第三个有两个,依此类推.在每个列表中,兄弟姐妹的顺序是无关紧要的,因为它们将被并行处理.

解决方法:

您的问题表明您希望此图表的输出为[[1,2,4,6],[3],[5],[7],[8,9,10]]. IIUC,模式如下:

> [1,2,4,6]是没有边缘的节点.
假设所有先前的节点都被擦除,则[3]是没有边缘的节点.
假设所有先前的节点都被擦除,则[4]是没有边缘的节点.
>等等(直到所有节点都被删除)

假设我们开始

g = networkx.DiGraph()
g.add_edges_from([[1,3],[2,3],[3,5],[4,5],[5,7],[6,7],[7,8],[7,9],[7,10]])

然后我们可以将其编码为

def find_levels(g):
    levels = []
    while g.nodes():
        no_in_nodes = [n for (n, d) in g.in_degree(g.nodes()).items() if d == 0]
        levels.append(no_in_nodes)
        for n in no_in_nodes:
            g.remove_node(n)
    return levels

如果我们运行它,我们得到结果:

>>> find_levels(g)
[[1, 2, 4, 6], [3], [5], [7], [8, 9, 10]]

这里的复杂性是Θ(| V | 2 | E |).可以使用Fibonnacci Heap构建更复杂的版本.基本上,所有顶点都需要放入堆中,每个级别由度数为0的顶点组成.每次弹出一个,并删除其他顶点的边缘,我们可以将其转换为堆减少键操作(剩余顶点的度数减少).这会将运行时间减少到Θ(| V | log(| V |)| E |).

标签:python,algorithm,graph,graph-theory,networkx
来源: https://codeday.me/bug/20190527/1165767.html