【问题标题】:How to identify root nodes in a python dictionary?如何识别python字典中的根节点?
【发布时间】:2019-07-04 05:03:28
【问题描述】:

我有一个表示图形的 python 字典。我希望识别根/独立节点,以便我可以同时处理它们,然后下一个节点将成为根/独立节点。 我对如何在 python 中实现这种技术感到困惑。

下面是一个示例字典:

my_graph = {
            1:[4],
            2:[6],
            3:[9],
            4:[5,7],
            5:[8],
            6:[],
            7:[],
            8:[],
            9:[]
           }

我会将这个过程分成不同的框架。取决于上述字典的预期结果如下:

1- 开始: 根/独立节点 = 1,2,3

2- 在第 1 帧之后 根/独立节点 = 4,6,9

3- 在第 2 帧之后 根/独立节点 = 5,7

4- 在第 3 帧之后 根/独立节点 = 8

编辑 1: 我正在尝试以任何形式获取序列,例如给定字典中节点依赖图的列表、数组或任何其他类似的数据结构,其中每个子节点都依赖于其父节点,因此不能在父节点之前处理。作为下一步,我希望获得一些并行性,即我可以一次处理所有根节点。

我一直在阅读有关 Daskluigui 的信息,但不确定它们是否是最终解决方案,或者我可以通过一些简单的方法来解决。

【问题讨论】:

  • 到目前为止你尝试过什么?请用代码演示一下。
  • 您能提供更多上下文吗?如果我们看到您想要解决的问题,这将有助于回答您的问题。
  • @thomi 我在“编辑 1”标签下添加了解释。如果您仍然无法理解我,请提出更多问题,我很乐意为您解释。或者你可以写出你目前对这个问题的理解。
  • @sophros 我试图在纸上找出解决方案。我写了很多 python 脚本,但这只是为了测试不同的想法。

标签: python data-structures graph


【解决方案1】:

这称为“拓扑排序”。一个简单的算法是

  1. 在节点和“传入”弧的数量之间建立映射
  2. 处理节点为 0(那些是“根”)并在您继续操作时更新计数器(当您处理所有邻居的节点递减计数器时)。

如果图形不是树(有循环),您可能会在完成之前停止。在这种情况下,您将到达图表不为空但没有可用根的地步。

你的情况

def tsort(graph): 
    counts = dict((k, 0) for k in graph) 
    for n, neighbors in graph.items(): 
        for nh in neighbors: 
            counts[nh] = counts[nh] + 1 
    while graph: 
        roots = [k for k in graph if counts[k] == 0] 
        if not roots: 
            raise RuntimeError("Cycles present, no topological sort possible") 
        print("roots", roots) 
        for r in roots: 
            print("Processing", r) 
            for nh in graph[r]: 
                counts[nh] -= 1 
            del graph[r] 

【讨论】:

  • @muruDiaz:是的...根是没有任何“传入”链接的所有节点,它们可以不止一个。唯一的问题是循环(在这种情况下不可能进行拓扑排序)。
【解决方案2】:

听起来你想执行Topological Sort

您可以使用库,toposort 为您完成提升,它将确定应处理节点的依赖关系和顺序:

import toposort

my_graph = {
            1:[4],
            2:[6],
            3:[9],
            4:[5,7],
            5:[8],
            6:[],
            7:[],
            8:[],
            9:[]
           }

# change values to sets (required by toposort)
for key, value in my_graph.items():
    my_graph[key] = set(value)

result = toposort.toposort(my_graph)
print(list(result))

[{6, 7, 8, 9}, {2, 3, 5}, {4}, {1}]

【讨论】:

  • 我不认为这是预期的输出
【解决方案3】:

容易多了:

while d: #'d' is a dictionary
    roots = set(d).difference(*d.values())
    print(roots)
    [d.pop(k) for k in roots]

或以递归方式:

def traverse(d):
    if d:
        roots = set(d).difference(*d.values())
        print(roots)
        [d.pop(k) for k in roots]
        return traverse(d)

无论哪种方式打印:

set([1, 2, 3])
set([4, 6, 9])
set([5, 7])
set([8])

【讨论】:

  • 哪一个更适合越来越大的字典?你能分享他们的性能比较吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多