【问题标题】:Topological sort (Kahn's algorithm) trouble拓扑排序(卡恩算法)的麻烦
【发布时间】:2017-02-13 10:47:50
【问题描述】:

我无法在嵌套的 for 循环中环绕我的代码。我在 wiki 上关注卡恩算法:Kahn's。我不明白如何测试 outboundEdge 是否有每个 endArray 元素 (m) 的传入边。

这是我目前所拥有的:

    def topOrdering(self, graph):

    retList = []
    candidates = set()
    left = []
    right = []

    for key in graph:
        left.append(key)
        right.append(graph[key])

    flattenedRight = [val for sublist in right for val in sublist]

    for element in left:
        if element not in flattenedRight:
            #set of all nodes with no incoming edges
            candidates.add(element)

    candidates = sorted(candidates)

    while len(candidates) != 0:
        a = candidates.pop(0)
        retList.append(a)
        endArray = graph[a]

        for outGoingEdge in endArray:

            if outGoingEdge not in flattenedRight:
                candidates.append(outGoingEdge)
                #flattenedRight.remove(outGoingEdge)

            del outGoingEdge


    if not graph:
        return "the input graph is not a DAG"
    else:
        return retList

这是一张可视化我的算法的图片。图是邻接表的形式。

【问题讨论】:

    标签: python algorithm topological-sort


    【解决方案1】:

    您可以单独存储indegree(传入边数),并在每次从空集中删除顶点时递减计数。当 count 变为 0 时,将顶点添加到空集以供稍后处理。示例如下:

    def top_sort(adj_list):
        # Find number of incoming edges for each vertex
        in_degree = {}
        for x, neighbors in adj_list.items():
            in_degree.setdefault(x, 0)
            for n in neighbors:
                in_degree[n] = in_degree.get(n, 0) + 1
    
        # Iterate over edges to find vertices with no incoming edges
        empty = {v for v, count in in_degree.items() if count == 0}
    
        result = []
        while empty:
            # Take random vertex from empty set
            v = empty.pop()
            result.append(v)
    
            # Remove edges originating from it, if vertex not present
            # in adjacency list use empty list as neighbors
            for neighbor in adj_list.get(v, []):
                in_degree[neighbor] -= 1
    
                # If neighbor has no more incoming edges add it to empty set
                if in_degree[neighbor] == 0:
                    empty.add(neighbor)
    
        if len(result) != len(in_degree):
            return None # Not DAG
        else:
            return result
    
    ADJ_LIST = {
        1: [2],
        2: [3],
        4: [2],
        5: [3]
    }
    
    print(top_sort(ADJ_LIST))
    

    输出:

    [1, 4, 5, 2, 3]
    

    【讨论】:

    • 啊,我忘了说,不允许空键。
    • @JeffreyPhung 你是什么意思不允许空键? 3 不应该在邻接列表中,因为没有传出边?
    • 我给定的邻接列表不包含 3 个。所以从你的逻辑来看,会有一个异常错误,这就是我试图按照我的方式去做的原因。以你的方式,我想我必须再次为每个邻居创建另一个邻接列表?
    • @JeffreyPhung 在这种情况下,您可以进行较小的更改并使用空列表作为默认邻居,并将结果长度与入度而不是邻接列表进行比较。我已经相应地修改了答案。
    • 非常感谢!绝对比我想的要好。
    猜你喜欢
    • 2017-09-27
    • 2019-08-07
    • 1970-01-01
    • 2014-05-20
    • 2020-10-26
    • 2021-07-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多