【发布时间】:2022-01-22 14:49:01
【问题描述】:
Dijkstra 算法的这个特定实现的时间复杂度是多少?
当你使用最小堆时,我知道this question 的几个答案,比如 O(E log V),this article 和 this article 也是如此。但是,article here 表示 O(V+ElogE),它的逻辑与下面的代码相似(但不完全相同)。
算法的不同实现可以改变时间复杂度。我正在尝试分析下面实现的复杂性,但是检查visitedSet 和忽略minHeap 中的重复顶点等优化让我怀疑自己。
这是伪代码:
// this part is O(V)
for each vertex in graph {
distanceMap[vertex] = infinity
}
// initialize source vertex
minHeap.add(source vertex and 0 distance)
distanceMap[source] = 0
visitedSet.add(source vertex)
// loop through vertices: O(V)?
while (minHeap is not empty) {
// Removing from heap is O(log n) but is n the V or E?
vertex and distance = minHeap.removeMin
if (distance > saved distance in distanceMap) continue while loop
visitedSet.add(vertex)
// looping through edges: O(E) ?
for (each neighbor of vertex) {
if (visitedSet contains neighbor) continue for loop
totalDistance = distance + weight to neighbor
if (totalDistance < saved distance in vertexMap) {
// Adding to heap is O(log n) but is n the V or E?
minHeap.add(neighbor and totalDistance)
distanceMap[neighbor] = totalDistance
}
}
}
注意事项:
- 从源顶点可到达的每个顶点将至少被访问一次。
- 检查每个顶点的每条边(邻居),但如果在
visitedSet中则忽略 - 仅当邻居的距离小于当前已知距离时,才会将邻居添加到堆中。 (假设未知距离的默认长度为无穷大。)
这个实现的实际时间复杂度是多少?为什么?
【问题讨论】:
-
只是为了确定:不会对这个伪代码进行任何更改,而且您也不想优化它,对吧?
-
正如您在代码中提到的,minHeap 存储的距离是边的权重,但是,这些权重的数量最多是顶点的数量。因此,while 循环最多迭代 O(v) 次,添加到堆或从堆中删除将是 O(log(v))。此外,我认为循环一个顶点的邻居也是 O(v) 而不是 O(E),因为特定顶点最多有 v-1 个邻居。
-
没有执行 O(E + log V) 的 dijkstra 算法。其中大多数是 O(E * log V)。我访问了您的参考资料link,但它表明时间复杂度为 O(E * log V)。
-
@trincot,是的,没错。
-
@CodePlus,感谢您发现我的错误。我已经更新了问题。
标签: algorithm graph time-complexity big-o dijkstra