Algorithm 为什么BFS的复杂性是O(V&x2B;E)而不是O(E)?

Algorithm 为什么BFS的复杂性是O(V&x2B;E)而不是O(E)?,algorithm,time-complexity,big-o,depth-first-search,breadth-first-search,Algorithm,Time Complexity,Big O,Depth First Search,Breadth First Search,这是一个通用的BFS实现: 对于具有V节点和E边总数的连通图,我们知道每个边在内环中将被考虑两次。因此,如果BFS的内环中的迭代总数将是2*边数E,那么运行时不是将是O(E)?这是一种需要更深入地研究实现的情况。特别是,如何确定是否访问了节点 传统算法通过对顶点着色来实现这一点。所有顶点一开始都是白色的,访问时会变为黑色。因此,只需查看顶点的颜色即可确定访问。如果您使用这种方法,那么您必须在开始时将每个顶点的颜色设置为白色,从而完成相当于O(V)的初始化工作 你可以用不同的方式管理你的颜色。您

这是一个通用的BFS实现:


对于具有
V
节点和
E
边总数的连通图,我们知道每个边在内环中将被考虑两次。因此,如果BFS的内环中的迭代总数将是
2*边数E
,那么运行时不是将是
O(E)

这是一种需要更深入地研究实现的情况。特别是,如何确定是否访问了节点

传统算法通过对顶点着色来实现这一点。所有顶点一开始都是白色的,访问时会变为黑色。因此,只需查看顶点的颜色即可确定访问。如果您使用这种方法,那么您必须在开始时将每个顶点的颜色设置为白色,从而完成相当于O(V)的初始化工作

你可以用不同的方式管理你的颜色。您可以维护包含所有访问节点的数据结构。如果这样做,就可以避免O(V)初始化成本。但是,您将在数据结构的其他地方支付该费用。例如,如果您将它们全部存储在一个平衡树中,则如果w未被访问,则每个
现在的成本为O(log V)

这显然给了你一个选择。您可以使用传统的着色方法生成O(V+E),也可以通过将此信息存储在您自己的数据结构中生成O(E log V)

在问题中指定一个连通图。在这种情况下,O(V+E)=O(E),因为顶点的数量永远不能超过E+1。然而,BFS的时间复杂度通常是针对一个任意图给出的,该图可以包括一个非常稀疏的图

如果一个图足够稀疏(比如一百万个顶点和五条边),那么初始化的代价可能会很大,以至于您需要切换到O(elnv)算法。然而,这些在实际环境中是非常罕见的。在实际环境中,传统方法(给每个顶点一个颜色)的速度与更花哨的数据结构相比是如此之快,以至于除了非常稀疏的图之外,您对所有东西都选择了这种传统的着色方案


如果您在顶点上维护了一个专用的颜色属性,并使用一个不变的规则,即在算法调用之间所有节点都是黑色的,那么您可以通过对每个BFS执行两次来降低O(E)的成本。在第一次传递时,可以将它们全部设置为白色,然后进行第二次传递以将它们全部变为黑色。如果您有一个非常稀疏的图,这可能会更有效。

在这种情况下,您需要更深入地了解实现。特别是,如何确定是否访问了节点

传统算法通过对顶点着色来实现这一点。所有顶点一开始都是白色的,访问时会变为黑色。因此,只需查看顶点的颜色即可确定访问。如果您使用这种方法,那么您必须在开始时将每个顶点的颜色设置为白色,从而完成相当于O(V)的初始化工作

你可以用不同的方式管理你的颜色。您可以维护包含所有访问节点的数据结构。如果这样做,就可以避免O(V)初始化成本。但是,您将在数据结构的其他地方支付该费用。例如,如果您将它们全部存储在一个平衡树中,则如果w未被访问,则每个
现在的成本为O(log V)

这显然给了你一个选择。您可以使用传统的着色方法生成O(V+E),也可以通过将此信息存储在您自己的数据结构中生成O(E log V)

在问题中指定一个连通图。在这种情况下,O(V+E)=O(E),因为顶点的数量永远不能超过E+1。然而,BFS的时间复杂度通常是针对一个任意图给出的,该图可以包括一个非常稀疏的图

如果一个图足够稀疏(比如一百万个顶点和五条边),那么初始化的代价可能会很大,以至于您需要切换到O(elnv)算法。然而,这些在实际环境中是非常罕见的。在实际环境中,传统方法(给每个顶点一个颜色)的速度与更花哨的数据结构相比是如此之快,以至于除了非常稀疏的图之外,您对所有东西都选择了这种传统的着色方案


如果您在顶点上维护了一个专用的颜色属性,并使用一个不变的规则,即在算法调用之间所有节点都是黑色的,那么您可以通过对每个BFS执行两次来降低O(E)的成本。在第一次传递时,可以将它们全部设置为白色,然后进行第二次传递以将它们全部变为黑色。如果你有一个非常稀疏的图,这可能会更有效。

好吧,让我们把它分成几个简单的部分

  • 您保存了一个已访问的数组,通过查找它,您可以决定是否将
    节点推入
    队列。一旦访问,您就不会再推它了。那么,有多少节点被推到队列中:
    (当然)V节点
    。它的复杂性是O(V)

  • 现在,每次从队列中取出
    一个节点
    ,并访问其所有
    相邻节点
    。现在,按照这个方法,
    对于所有的V节点
    ,您将遇到多少节点。如果图形是单向的,则是边数,如果图形是双向的,则是边数。因此,对于
    单向的
    O(E)
    O(2*E)
    双向的

  • 因此,最终的(即总的)复杂性将是
    O(V+e)
    O(V+2*e)
    一般来说
    ,我们可以说
    O(V+e)

    <
    1 ---- 2
    |
    |
    3 ---- 4