如何分析DAG时间复杂度?

时间:2016-12-16 18:40:53

标签: python algorithm

我正在学习拓扑排序和图表。我在下面使用DFS实现了一个版本,但是我无法理解为什么维基百科页面说这是O(| V | + | E |)并分析它的时间复杂度,以及| V | + | E |之间的差异。和n ^ 2一般。

首先,我有两个for循环,逻辑说它会是(n ^ 2)但是在任何DAG(或树)中都有n-1个边和n个顶点?如果我们可以删除" -1"这与n ^ 2有何不同?没有重要价值?

graph = {
 1:[4, 5, 7],
 2:[3,5,6],
 3:[4],
 4:[5],
 5:[6,7],
 6:[7],
 7:[]
}



from collections import defaultdict

def topological_sort(graph):
    ordered, marked = [], defaultdict(int)

    while len(ordered) < len(graph):
        for vertex in graph:
           if marked[vertex]==0:
                visit(graph, vertex, ordered, marked)

return ordered

def visit(graph, n, ordered, marked):
    if marked[n] == 1:
        raise 'Not a DAG'

    marked[n] = 1

    for neighbor in graph.get(n):
        if marked[neighbor]!=2:
            visit(graph, neighbor, ordered, marked)

    marked[n] = 2

    ordered.insert(0, n)


def main():
print(topological_sort(graph))

main()

1 个答案:

答案 0 :(得分:1)

正确的实现在O(|V| + |E|)时间内有效,因为它最多遍历每个边缘和每个顶点一次。对于完整(或几乎完整的图表),它与O(|V|^2)相同。但是,当图形稀疏时,它会好得多。

您的实施是O(|V|^2),而不是O(|V| + |E|)。这两个嵌套循环:

while len(ordered) < len(graph):
    for vertex in graph:
         if marked[vertex]==0:
               visit(graph, vertex, ordered, marked)

在最糟糕的情况下进行1 + 2 ... + |V| = O(|V|^2)次迭代(例如,对于空图)。你可以通过摆脱外循环轻松修复(它很简单:只需删除while循环。你不需要它。)