【问题标题】:Graph traversal ensuring the parents are visited first图遍历确保首先访问父母
【发布时间】:2016-08-02 20:54:00
【问题描述】:

我正在尝试创建一个工作流管理,我用图表来表示工作流。该图是一个简单的有向图,其中节点表示一些任务,边缘指向依赖于该任务且具有父->子关系的任务。现在,我想要实现的是,在所有父项都完成之前,任何任务都不应该开始。

假设我将以下图表表示为 python 字典:

graph = {'A': ['B', 'D'], 'B': ['D', 'C'], 'C': ['D', 'E'],
     'D': ['E'], 'E': []}

在这种情况下,A 应该首先执行,然后是 B,然后是 C。之后D 被执行,最后任务E 完成,这取决于D

我可以设想这样做的一种方法是使用广度或深度优先搜索来访问所有节点,然后检查每个节点是否已完成所有父节点。如果是,我开始该任务,并一直这样做,直到所有任务都已开始。

我想知道是否有任何更复杂/有效的解决方案来解决这个问题,而不是多次遍历图表?

【问题讨论】:

标签: algorithm graph graph-algorithm


【解决方案1】:

这取决于您的图形数据结构。

如果您的图形存储为节点,则可以使用 BFS,因为您将通过从同级到同级(具有相同依赖级别的任务)从根(最大任务依赖)导航到叶(最小任务依赖)。

如果您的图按照您的解释存储为邻接列表,您应该进行拓扑排序,以逐步从最大任务依赖关系到最小任务依赖关系。

这会给你那么 O(n) 的遍历图的复杂度。

【讨论】:

    【解决方案2】:

    您不需要多次遍历。只需一个普通的 BFS 就可以完成这项工作。在 BFS 中,总是先访问父节点。

    【讨论】:

      【解决方案3】:

      您可以使用像 graph_tool 这样实现了 topological sort 的库:

      graph = {'A': ['B', 'D'], 'B': ['D', 'C'], 'C': ['D', 'E'], 'D': ['E'], 'E': []}
      i2a = dict(enumerate(graph))
      a2i = {v:k for k,v in i2a.items()}
      
      import graph_tool.all as gt
      g = gt.Graph()
      g.add_edge_list([(a2i[s], a2i[t]) for s in graph for t in graph[s]])
      print(*[i2a[v] for v in gt.topological_sort(g)])
      

      输出:

      A B C D E
      

      【讨论】:

      • 也感谢您的提示。我对可以使用的外部库有一些限制,但知道这一点非常有用!
      猜你喜欢
      • 2022-08-17
      • 1970-01-01
      • 1970-01-01
      • 2018-07-15
      • 1970-01-01
      • 1970-01-01
      • 2011-09-25
      • 2021-04-16
      • 1970-01-01
      相关资源
      最近更新 更多