algorithm - 复杂性 - Dijkstra 算法

标签 algorithm time-complexity complexity-theory

假设我已经使用 PriorityQueue 实现了 dijkstras,因此在未访问的节点中添加和删除需要 O(log n)。

PQ 最多包含 E 个节点,因此清空它我们得到 O(E)。当 PQ 不为空时,我们选择最好的节点并将其删除,如果未访问则访问并遍历其所有邻居(可能将它们添加到 PQ)。

我不明白的是:对于最坏的 E 项,遍历所有邻居(最坏的 V)怎么可能没有 O(E*V) 的时间复杂度。我看到了太多的解释,我们应该只看操作并观察它们将执行多少次并从中得出我们的结论。我不明白我们怎么能忽视我们正在循环 V 个邻居这一事实,n 个项目的空 for 循环仍然是 O(n)?

对我来说,最终的复杂度似乎是 O(V + E*V log E) 而不是 O(V + V log E)。我的意思是有很多差异,但重点是我遗漏了一些微不足道的东西 :P

最佳答案

您似乎混淆了术语的第一点。 E不是项目的数量,它是顶点之间的边数。 V是顶点的数量,这(取决于上下文)很可能是项目的数量。

接下来,“这个顶点是那个顶点的邻居”意味着它们之间有一条边。每条边贡献 2 个邻居关系。 (每个方向一个。)因此 2 E是可以存在的邻居关系的个数,total。

您的直觉是 V 中的每一个节点最多可以有 V-1邻居共V<sup>2</sup>-V邻居关系是正确的 - 但您可以从边的数量判断您与最坏情况的接近程度。

因此,我们最终完成了以下潜在工作:

for each of E edges:
    for each vertex on that edge:
        O(1) work to check whether it was processed yet
        (processing the vertex if needed accounted for separately)

for each of V vertices:
    O(log(V)) to add to the priority queue
    O(log(V)) to remove from the priority queue
    (processing its edges accounted for separately

第一个 block 是O(E) .第二 block 是 O(V log(V)) .总数是O(E + V log(V)) .

希望这个解释能澄清为什么会如此复杂。

关于algorithm - 复杂性 - Dijkstra 算法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53838596/

相关文章:

c - 在链表的末尾插入一个元素?

java - 更改合并排序后的运行时间复杂度是多少

linux-kernel - 为什么要从 O(1) 调度程序转移到 O(log N) 的 CFS?

arrays - 插入排序理论分析,总移位数。

python - 通过添加某些列的值从 Excel 行中删除重复项

algorithm - 函数式语言的快速元素查找(Haskell)

algorithm - 安德鲁算法的时间复杂度(复杂的船体)

python - 使用 zip() 函数的 Python 列表理解的复杂度为 O(n)

c# - 递归比迭代快

c# - 二维离散傅里叶变换的复杂性