寻求算法反转(反向镜像?从里到外翻转)DAG

时间:2009-02-27 14:39:54

标签: algorithm graph-theory directed-acyclic-graphs

我正在寻找一种“反转”算法(反向?从里到外翻?)a DAG:

       A*      # I can't ascii-art the arrows, so just
      / \      # pretend the slashes are all pointing
     B   C     # "down" (south-east or south-west)
    /   / \    # e.g. 
   G   E   D   # A -> (B -> G, C -> (E -> F, D -> F))
        \ /
         F

我正在使用的表示是真正的DAG(没有 “父母”指针)。我想以某种方式遍历图表 同时使用等效节点构建“镜像”图形 节点间关系的方向倒置。

         F*
        / \
   G*  E   D   # F -> (E -> C -> A, D -> C -> A), G -> B -> A
    \   \ /    # 
     B   C     # Again, arrows point "down"
      \ /      # 
       A       # 

所以输入是一组“根”(这里是{A})。输出应该是a 结果图中的“根”集:{G,F}。 (根据我的意思是一个节点 没有传入的参考。叶子是没有传出的节点 的引用。)

输入的根源成为输出和签证的叶子 反之亦然。转型应该是自身的逆转。

(好奇的是,我想为我正在使用的库添加一个功能 表示用于结构查询的XML,我可以通过它来映射每个节点 第二棵树中的第一棵树到它的“镜像”(又回来了 再次)为我的查询规则提供更多的导航灵活性。)

5 个答案:

答案 0 :(得分:9)

遍历图形,构建一组反向边和叶节点列表。

使用叶子(现在是根)节点开始对反转边缘进行拓扑排序。

根据从排序列表末尾开始的反转边构造反转图。由于节点以反向拓扑顺序构造,因此可以保证在构造节点之前构造给定节点的子节点,因此可以创建不可变表示。

如果您使用中间表示的结构跟踪与节点关联的两个方向上的所有链接,则为O(N);如果使用排序查找节点的所有链接,则为O(NlnN)。对于小图形或不受堆栈溢出影响的语言,您可以只是懒惰地构造图形而不是显式执行拓扑排序。所以它取决于你实现它的一点点,这将是多么不同。

A -> (B -> G, C -> (E -> F, D -> F))

original roots: [ A ]
original links: [ AB, BG, AC, CE, EF, CD, DF ] 
reversed links: [ BA, GB, CA, EC, FE, DC, FD ]
reversed roots: [ G, F ]
reversed links: [ BA, CA, DC, EC, FE, FD, GB ] (in order of source)
topologically sorted: [ G, B, F, E, D, C, A ]
construction order : A, C->A, D->C, E->C, F->(D,E), B->A, G->B

答案 1 :(得分:2)

只需进行深度优先搜索标记,然后每次遍历箭头时,向结果DAG添加反向标记。将叶子添加为根。

答案 2 :(得分:2)

我的直观建议是对图表执行Depth First遍历,并同时构建镜像图。

遍历每个节点时,在镜像图中创建一个新节点,并在新图中创建它与其前任节点之间的边。

如果您在任何时候到达没有孩子的节点,请将其标记为根。

答案 3 :(得分:1)

我通过简单的图遍历解决了这个问题。请记住,拓扑排序仅对有向无环图有用。

我使用了邻接列表,但你可以用邻接矩阵做类似的事情。

在Python中它看起来像这样:

# Basic Graph Structure
g = {}
g[vertex] = [v1, v2, v3] # Each vertex contains a lists of its edges

要查找v的所有边,然后遍历列表g [v],这将为您提供所有(v,u)边。

要构建反转图形,请创建一个新字典并构建如下:

    reversed = {}
    for v in g:
        for e in g[v]:
            if e not in reversed:
                reversed[e] = []
            reversed[e].append(v)

这对于大型图形来说是非常耗费内存的(将内存使用量增加一倍),但这是一种非常简单的方法,可以非常快速地使用它们。可能有更聪明的解决方案涉及构建生成器和使用某种类型的dfs算法,但我没有深思熟虑。

答案 4 :(得分:-1)

Depth-first search可能能够生成您所追求的内容:注意您在树中的路径,每次遍历时都会向生成的DAG添加反向(叶子是根)。