有向无环图DAG

如果子节点可以有多个父节点,那么我们实际上处理的是一个有向无环图(DAG)而不是树。在DAG中,一个节点可以有多个前驱(父节点)。在这种情况下,我们可以使用广度优先搜索(BFS)来遍历图,但需要注意的是,我们必须确保在遍历过程中不会重复访问节点。
以下是使用Python实现的一个DAG的广度优先遍历(BFS)编码示例,其中每个节点可以有一个或多个父节点:

from collections import deque, defaultdict
class Node:
    def __init__(self, value):
        self.value = value
        self.parents = []  # 父节点列表
        self.children = []  # 子节点列表
    def add_parent(self, parent_node):
        self.parents.append(parent_node)
    def add_child(self, child_node):
        self.children.append(child_node)
def bfs_encode_dag(root_nodes):
    if not root_nodes:
        return []
    queue = deque(root_nodes)
    node_codes = {
    
    }  # 存储节点的编码
    code = 0  # 初始化编码值
    visited = set()  # 记录已访问的节点
    while queue:
        current_node = queue.popleft()
        
        # 如果节点已经访问过,则跳过
        if current_node in visited:
            continue
        # 标记节点为已访问
        visited.add(current_node)
        node_codes[current_node] = code  # 对当前节点进行编码
        code += 1
        # 将子节点加入队列
        for child in current_node.children:
            queue.append(child)
    return node_codes
# 创建DAG的节点
root = Node('root')
child_a = Node('A')
child_b = Node('B')
child_c = Node('C')
child_d = Node('D')
child_e = Node('E')
# 添加子节点和父节点
root.add_child(child_a)
root.add_child(child_b)
child_a.add_child(child_c)
child_a.add_child(child_d)
child_b.add_child(child_e)
child_c.add_parent(child_b)  # child_c 有两个父节点
# 执行广度优先遍历并编码
encoded_nodes = bfs_encode_dag([root])
# 打印编码结果
for node, code in encoded_nodes.items():
    print(f"节点 {
      
      node.value} 的编码是: {
      
      code}")

在这个例子中,我们首先定义了一个Node类,它有parentschildren两个列表来分别存储父节点和子节点。我们修改了bfs_encode_dag函数,使其能够接受一个根节点列表,并且使用了一个visited集合来跟踪已经访问过的节点,以避免重复访问。
在添加节点间关系时,child_c节点被添加为child_b的子节点,同时也作为child_a的子节点,这表明了它可以有多个父节点。
请注意,这个例子中的编码是基于节点在BFS遍历中首次被访问的顺序。如果图中存在多个独立的子图(即不相连的部分),那么你可能需要修改bfs_encode_dag函数来处理这种情况,例如通过初始化多个根节点来启动遍历。

猜你喜欢

转载自blog.csdn.net/weixin_32759777/article/details/143220978