Python中使用逆邻接表解决拓扑排序问题

2023-04-11 00:00:00 排序 邻接 拓扑

拓扑排序是一种针对有向无环图(DAG)的排序算法,可以将DAG中所有顶点排成一个线性序列,使得对于任意一条边(u,v),顶点u都排在顶点v的前面。在实际应用中,拓扑排序有着广泛的应用,例如编译器的代码优化、任务调度等领域。

Python中使用逆邻接表来解决拓扑排序问题,逆邻接表可以快速地找到顶点的入度信息,从而实现拓扑排序。逆邻接表是一个字典类型的数据结构,其中每个顶点v对应一个列表,列表包含了所有以v为终点的有向边的起点集合。

下面是Python代码演示拓扑排序的过程,具体思路如下:

  1. 首先将所有顶点的入度初始化为0,将所有边的终点对应的顶点入度加1。

  2. 使用一个队列来存储入度为0的顶点。

  3. 将队列中的顶点出队,并将其所有邻接点的入度减1,如果减1后入度为0,则将其加入到队列中。

  4. 重复执行步骤3,直到队列为空。

  5. 如果最终所有顶点的入度都为0,则说明拓扑排序成功,并返回拓扑排序的结果。

代码如下:

from collections import defaultdict

def topo_sort(graph):
    # 建立逆邻接表
    reverse_graph = defaultdict(list)
    for u in graph:
        for v in graph[u]:
            reverse_graph[v].append(u)

    # 初始化入度为0的顶点
    in_degree = {u: 0 for u in graph}
    for u in graph:
        for v in graph[u]:
            in_degree[v] += 1

    # 将入度为0的顶点加入队列
    queue = [u for u in in_degree if in_degree[u] == 0]

    # 拓扑排序
    result = []
    while queue:
        u = queue.pop(0)
        result.append(u)
        for v in reverse_graph[u]:
            in_degree[v] -= 1
            if in_degree[v] == 0:
                queue.append(v)

    # 如果存在入度不为0的顶点,则说明存在环
    if len(result) != len(graph):
        return None
    else:
        return result

测试代码如下:

graph = {
    "a": ["b", "c"],
    "b": ["d"],
    "c": ["d"],
    "d": []
}
print(topo_sort(graph))  # ["a", "c", "b", "d"]

graph = {
    "a": ["b", "c"],
    "b": ["d"],
    "c": ["d"],
    "d": ["a"]
}
print(topo_sort(graph))  # None

上述代码中,第一个图是一个DAG,可以通过拓扑排序得到正确的结果;第二个图中存在环,无法通过拓扑排序得到正确的结果,返回None。

相关文章