简体   繁体   English

DAG - 遍历图 - bfs 但父母优先

[英]DAG - Iterate over graph - bfs but parents first

Hello I have a dag that looks like this你好,我有一个看起来像这样的 dag

我的图表

I'd like to travel it from the roots and print output like我想从根部开始旅行并打印 output 之类的

1 6
2 3
4
5

I tried something like this but it's still not working.我尝试过这样的事情,但它仍然无法正常工作。 Could someone give me a tip on how such algorithm should look like or the name of this kind of graph traversal?有人可以给我一个关于这种算法应该是什么样子或这种图遍历的名称的提示吗?

from typing import List


class Node:
    def __init__(self, value, children) -> None:
        super().__init__()
        self.value = value
        self.children = children

    @staticmethod
    def create(value, *parents):
        node = Node(value, [])
        if parents is not None:
            for parent in parents:
                parent.children.append(node)
        return node


def travel(roots: List[Node], visited: List[Node]):
    print(" ".join([str(r.value) for r in roots]))
    visited += roots
    all_children = []
    for r in roots:
        if r.children:
            for c in r.children:
                if c not in visited:
                    all_children.append(c)
    if all_children:
        travel(all_children, visited)


if __name__ == '__main__':
    root = Node.create(1)
    root2 = Node.create(6)
    roots = [root, root2]
    n2 = Node.create(2, root)
    n3 = Node.create(3, root)
    n4 = Node.create(4, n2, n3, root2)
    n5 = Node.create(5, n4)
    travel(roots, [])

You could first traverse all nodes like you did, but then register for each node how many parents it has.您可以像以前一样首先遍历所有节点,然后为每个节点注册它有多少父节点。

Put the nodes in a priority queue based on the number of parents they have.根据节点的父节点数量将节点放入优先队列中。 This can be implemented as a plain list, where the index represents the number of parents, and the associated value is a list of nodes that have that number of parents.这可以实现为一个普通列表,其中索引表示父节点的数量,关联的值是具有该数量父节点的节点列表。

Then output all nodes that have no parents according to that priority queue.然后 output 根据该优先级队列,所有没有父节点的节点。 At the same time remove them from that priority queue and also decrement the parent count of the children of those nodes.同时将它们从该优先级队列中删除,并减少这些节点的子节点的父计数。

Repeat this process until the queue is empty.重复此过程,直到队列为空。

def travel(roots: List[Node]):
    # Build dictionary keyed by node to register their number of parents
    parentcount: Dict[Node, int] = { node: 0 for node in roots }
    # Visit each node, and update that parent count for each of its children
    visited: Set[Node] = set()
    nodes: List[Node] = roots
    while nodes:
        nextlevel: List[Node] = []
        for node in nodes:
            if node not in visited and node.children:
                for child in node.children:
                    parentcount[child] = parentcount.get(child, 0) + 1
                nextlevel.extend(node.children)
        visited.update(nodes)
        nodes = nextlevel
    # Make prioritiy queue: reverse the parentcount information: 
    #    group nodes that have the same parent count
    buckets: List[Set[Node]] = [set() for _ in visited]
    for node in visited:
        buckets[parentcount[node]].add(node)
    # Now we have the information to generate the output
    while buckets[0]:
        # Output nodes that have a parent count of 0. 
        nodes: List[Node] = list(buckets[0])
        buckets[0].clear()
        print(" ".join(str(node.value) for node in nodes))
        # Decrease the parent count of their children
        for node in nodes:
            if node.children:
                for child in node.children:
                    buckets[parentcount[child]].remove(child)
                    parentcount[child] -= 1
                    buckets[parentcount[child]].add(child)

NB: this function no longer takes the second argument.注意:这个 function 不再接受第二个参数。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM