【问题标题】:How is Big-O of Depth-First-Search = O(V+E)? [duplicate]深度优先搜索的大 O = O(V+E) 如何? [复制]
【发布时间】:2015-11-12 05:18:57
【问题描述】:

我试图了解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) 的?

谁能提供见解?

【问题讨论】:

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


    【解决方案1】:

    让我们把它变得简单。

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

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

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

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

    【讨论】:

    • 附带说明一下,您可能应该避免为 big-O 表示法编写“sum”之类的操作。这些东西不是数字或类似的东西,它们是一组函数。没有为函数集定义+。你暗示O(1)+O(1)=O(2)如果你理解它的真正含义,应该竖起你背上的毛。
    • 我以为我正在删除第 4 行的边缘
    • S 是节点列表,而不是边列表。您只删除节点。
    猜你喜欢
    • 1970-01-01
    • 2019-01-29
    • 2022-01-21
    • 2013-05-05
    • 1970-01-01
    • 1970-01-01
    • 2011-01-31
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多