深度优先搜索的Big-O如何= O(V + E)?

时间:2015-11-12 05:18:58

标签: algorithm big-o time-complexity nested-loops asymptotic-complexity

我试图了解DFS的复杂性如何/为何是O(V + E)。这是我尝试分析伪代码迭代DFS的复杂性。

DFS(G, t)
{

1   stack S = new empty Stack of size G.|V|  ... O(1)
2   S.push(t)                                ... O(1)

3   while(S is not Empty)                    ... O(|V|), this will always be =<|V|
    {
4       u = S.pop()                          ... O(1)

5       if(u.visited = false)                ... O(1)
        {
6            u.visited = true                ... O(1)

7            for-each edge (u,v) in G.E      ... O(|E|), this will always be =<|E|
8                if(v.visited = false)       ... O(1)
9                    S.push(v)               ... O(1)
        }
    }
}

现在结合我们每行的复杂性:

O(1)+ O(1)+ O(| V |)[O(1)+ O(1)+ O(1)+ O(E)[O(1)+ O(1)] ] = O(2)+ O(V)+ O(V)+ O(V)+ O(V)+ O(V * E)+ O(V * E)= 4 * O(V)+ 2 * O(V * E)= O(V * E)

我没有得到O(V + E)?有人能用数学方式向我展示我们如何实现O(V + E)吗?

任何人都可以提供见解吗?

1 个答案:

答案 0 :(得分:4)

让我们这么简单。

外部循环,它只在S上循环一次,删除它看到的每个元素。因此,您的符号为O(|V|)

内部循环,它只在你的边缘上循环一次,移除它看到的每个元素。因此,您的符号为O(|E|)

但是,S的每个元素都不会删除每个边缘。您删除所有节点和所有边,因此O(|V|+|E|)

但应注意,上述内容仅适用于意图。你的实现相对比较糟糕,它实际上是O(|V|*|E|),因为你没有从列表中删除边缘,只是将节点标记为已访问。最后效果相同,但您仍然会为每个节点遍历每个边缘。