Algorithm 计算大时间复杂度

Algorithm 计算大时间复杂度,algorithm,graph,time-complexity,Algorithm,Graph,Time Complexity,以下算法的时间复杂度据报道为O(v+e),但我无法解释原因。感谢您的帮助 这就是问题所在:在加权(节点和边)有向无环图中,为每个顶点计算一个称为秩的属性。它是通过自下而上遍历图来计算的。对于退出节点,假定秩值等于其指定的权重。对于图中的任何其他节点,秩定义为: “节点的主要后继节点的秩”+“节点与其主要后继节点之间的边的宽度”+“节点的权重” 其中,节点的主要后继节点是具有最高秩值的节点 这就是我猜想算法的伪代码: For "every vertex" in the graph

以下算法的时间复杂度据报道为O(v+e),但我无法解释原因。感谢您的帮助

这就是问题所在:在加权(节点和边)有向无环图中,为每个顶点计算一个称为秩的属性。它是通过自下而上遍历图来计算的。对于退出节点,假定秩值等于其指定的权重。对于图中的任何其他节点,秩定义为:

“节点的主要后继节点的秩”+“节点与其主要后继节点之间的边的宽度”+“节点的权重”

其中,节点的主要后继节点是具有最高秩值的节点

这就是我猜想算法的伪代码:

     For "every vertex" in the graph
        For "every immediate successor" of the selected vertex
           [the statements ...]
        End
     End
按照正确的拓扑顺序选择节点,外部循环执行的次数正好是v次,导致O(v)时间复杂度。 内部循环(搜索后继循环)最多执行(v-1)次(我猜是在使用邻接矩阵的情况下),导致O(v)时间复杂度。
因此,我计算总时间复杂度O(v^2),根据报告的值O(v+e),这是不正确的。

如果使用邻接列表而不是邻接矩阵,则需要O(v+e)。因为您只访问每个节点一次(因为您跟踪访问了哪些节点),并且访问了每个边缘一次(因为您不会使用另一端有已访问节点的边缘)

这里有一些伪代码-

queue<Node> q;
startNode = (starting node)
bool[numNodes] visited;
while (visited.size() < numNodes) {
    [check if visited]
    [mark as visited]
    [set rank]
    [add successors to the queue if they're not visited]
}
队列q;
startNode=(起始节点)
访问了布尔[节点];
while(已访问.size()
如果使用邻接列表而不是邻接矩阵,则需要O(V+E)。因为您只访问每个节点一次(因为您跟踪访问了哪些节点),并且访问了每个边缘一次(因为您不会使用另一端有已访问节点的边缘)

这里有一些伪代码-

queue<Node> q;
startNode = (starting node)
bool[numNodes] visited;
while (visited.size() < numNodes) {
    [check if visited]
    [mark as visited]
    [set rank]
    [add successors to the queue if they're not visited]
}
队列q;
startNode=(起始节点)
访问了布尔[节点];
while(已访问.size()
如果您有一个邻接列表,则内循环将迭代总次数O(e),因为它基本上只访问每条边一次。@NicoSchertler如果我们正在寻找每个节点的前一个节点(例如,在一个类似的问题中,通过颠倒DAG来分配列组),该怎么办?正如您所建议的,使用adj列表是提取每个节点的后续节点的直接方法。但是它在提取前导时也有用吗?或者在这种情况下,我们需要使用adj矩阵,它需要v次迭代才能找到每个节点的前导,从而导致总时间复杂度为O(v^2)?您还可以将前导存储为邻接列表。如果您有邻接列表,则内部循环迭代的总次数为O(e)次数,因为它实际上只访问每条边一次。@NicoSchertler如果我们正在寻找每个节点的直接前导节点(例如,在一个类似的问题中,通过颠倒DAG来分配秩),该怎么办?正如您所建议的,使用adj列表是提取每个节点的后续节点的直接方法。但是它也可以用于提取前导,或者在这种情况下我们需要使用adj矩阵,它需要v次迭代来找到每个节点的前导,结果是O(v^2)总时间复杂度?您还可以将前置节点存储为邻接列表。唯一的问题是,由于每个节点的排名取决于其直接后续节点的排名(最大值函数),因此在每个步骤添加到队列中的节点都是未访问的节点,其直接后续节点已被访问。因此,每个边只访问一次,因为在使用adj列表时,提取节点的后续节点是直接进行的。但是,如果在另一个问题中,排名是颠倒计算的,这会是相同的吗?因为,在每个秩设置步骤中,我们都需要提取节点的前辈。使用adj列表还是在这种情况下使用adj矩阵是可行的?唯一的问题是,由于每个节点的秩取决于其直接后继节点的秩(Max函数),因此在每一步添加到队列中的节点都是未访问的节点,其直接后继节点已被访问。因此,每个边只访问一次,因为在使用adj列表时,提取节点的后续节点是直接进行的。但是,如果在另一个问题中,排名是颠倒计算的,这会是相同的吗?因为,在每个秩设置步骤中,我们都需要提取节点的前辈。使用adj列表或在这种情况下使用adj矩阵是否可行?