我试图了解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)吗?
任何人都可以提供见解吗?
答案 0 :(得分:4)
让我们这么简单。
外部循环,它只在S
上循环一次,删除它看到的每个元素。因此,您的符号为O(|V|)
。
内部循环,它只在你的边缘上循环一次,移除它看到的每个元素。因此,您的符号为O(|E|)
。
但是,S
的每个元素都不会删除每个边缘。您删除所有节点和所有边,因此O(|V|+|E|)
。
但应注意,上述内容仅适用于意图。你的实现相对比较糟糕,它实际上是O(|V|*|E|)
,因为你没有从列表中删除边缘,只是将节点标记为已访问。最后效果相同,但您仍然会为每个节点遍历每个边缘。