【问题标题】:Understanding Time Complexity for tree traversal using BFS使用 BFS 了解树遍历的时间复杂度
【发布时间】:2017-10-29 05:58:36
【问题描述】:

当我使用 BFS 遍历具有 n 个节点的树(不一定是二叉树)时,我试图了解时间复杂度。 根据我的理解,它应该是 O(n^2),因为我的外循环运行了 n 次,即直到队列不为空并且树包含 n 个节点。 我的内部 for 循环必须不断地将与特定节点关联的子节点添加到队列中。 (每个节点都有一个包含所有子节点地址的字典) 因此,例如,如果根节点有 n-1 个节点(因此所有这些节点都没有进一步的子节点),那么时间复杂度不会是 n*(n-1) = O(n^2)。

我的理解正确吗? 有什么办法可以在 O(n) 中完成吗?请解释一下。

【问题讨论】:

    标签: c++ algorithm time tree breadth-first-search


    【解决方案1】:

    Big-O 表示法表示时间复杂度的上限。你当然可以说 BFS 的时间复杂度是 O(n2),但这并不是一个严格的上限。

    要获得严格的上界,可以这样考虑 BFS:每个节点只会被加入队列一次,每个节点只会从队列中移除一次。每次添加和删除操作仅花费 O(1) 时间,因此时间复杂度为 O(n)。

    编辑

    要在树上实现 O(n) BFS,可以尝试实现以下伪代码。

    procedure bfs(root: root of the tree)
        q := an empty queue
        push root into q
    
        while q is not empty
            v := the element at the head of q
            for u := children of v
                push u into q
            pop v out of q
    

    【讨论】:

    • 好的,我想我应该重新提出我的问题,有没有更快的方法来实现算法?
    【解决方案2】:

    用节点和边的数量来描述图算法的复杂性通常更有用。通常 |V|用于表示节点数,|E|表示边数。

    在 BFS 中,我们访问每个 |V|节点一次并将其所有邻居添加到队列中。并且,在算法结束时,图中的每条边都被处理了一次。因此我们可以说 BFS 是 O(|V| + |E|)。

    在全连接图中,|E| = |V|(|V| - 1)/2。因此,对于完全连接的图,复杂度为 O(|V|^2) 是正确的;然而,对于已知稀疏的图,O(|V| + |E|) 被认为是更严格的分析。

    【讨论】:

    • 我想我应该重新提出我的问题,有没有更快的方法来实现算法?
    • 从您提供的描述来看,这听起来已经很理想了。您的算法应该是 O(V + E)。由于您的输入是一棵树,因此您知道 |E| = |V|-1。因此,您的算法是 O(V)。只有您的分析是不正确的,因为您假设每个节点可能有 n-1 个子节点,而实际上树中的每个节点不可能有那么多。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-02-16
    • 1970-01-01
    • 2021-08-25
    相关资源
    最近更新 更多