Python中使用DFS判断图(Graph)是否为DAG(Directed Acyclic Graph)

2023-04-11 00:00:00 python 判断 DFS

以下是使用DFS判断图是否为DAG的Python代码演示:

def is_dag(graph):
    """
    判断有向图是否为DAG
    :param graph: 有向图
    :return: True表示是DAG,False表示不是DAG
    """
    visited = set()  # 记录已访问过的节点
    stack = set()  # 记录在当前DFS路径中的节点
    for node in graph:
        if node not in visited:
            if dfs(node, visited, stack, graph):
                return False
    return True


def dfs(node, visited, stack, graph):
    """
    深度优先搜索
    :param node: 当前搜索的节点
    :param visited: 已访问过的节点集合
    :param stack: 在当前DFS路径中的节点集合
    :param graph: 图
    :return: True表示存在环,False表示不存在环
    """
    visited.add(node)
    stack.add(node)
    for neighbor in graph[node]:
        if neighbor not in visited:
            if dfs(neighbor, visited, stack, graph):
                return True
        elif neighbor in stack:
            return True
    stack.remove(node)
    return False


# 示例
graph1 = {
    'a': ['b', 'c'],
    'b': ['c', 'd'],
    'c': [],
    'd': ['a']
}
print(is_dag(graph1))  # False:存在环a->b->d->a

graph2 = {
    1: [2, 3],
    2: [4, 5],
    3: [5],
    4: [],
    5: []
}
print(is_dag(graph2))  # True:无环

graph3 = {
    'pidan': ['code', 'programming'],
    'code': ['python'],
    'programming': []
}
print(is_dag(graph3))  # True:无环

在上述示例代码中,函数is_dag()接收一个有向图作为参数,使用一个visited集合记录已访问过的节点,使用一个stack集合记录在当前DFS路径中的节点。然后对于每个未被访问过的节点,调用dfs()函数进行深度优先搜索。

函数dfs()接收当前搜索的节点node、已访问过的节点集合visited、在当前DFS路径中的节点集合stack和整个图graph作为参数。函数先将当前节点加入visitedstack中,然后遍历当前节点的所有邻居节点。如果某个邻居节点还未被访问过,则递归调用dfs()函数;如果某个邻居节点已经在当前DFS路径中,则说明存在环,返回True。最后将当前节点从stack中删除,表示已经结束在该节点的DFS路径,返回False。

在示例中,演示了三个图:graph1存在环,graph2为DAG,graph3为DAG。对这三个图分别调用is_dag()函数,可以验证结果是否符合预期。

相关文章