繁体   English   中英

Dijkstra的复杂性正确吗?

[英]Is the complexity of Dijkstra's correct?

我对Dijkstra算法的运行时复杂度有疑问。 (请参阅CLRS版本3中的伪代码):

DIJKSTRA(G, w, s)
1 INITIALIZE-SINGLE-SOURCE(G, s)
2 S ← ∅ 
3 Q ← V[G]
4 while Q != ∅ 
5   do u ← EXTRACT-MIN(Q)
6   S ← S ∪ {u} 
7   for each vertex v ∈ Adj[u]
8     do RELAX(u, v,w)

我知道第3行总计为O(V),第5行总计为O(VlogV); 第7行总计为O(E),第8行隐含了reduce_key(),因此每个Relax()操作的logV。 但是在Relax()中,在d [v]> d [u] + weight并决定放松之后,我们是否应该在调用reduce_key(Q,pos,d [v]之前先查询v在队列Q中的位置? )用d [v]替换pos的键? 请注意,此查找本身的成本为O(V)。 所以每个Relax()应该花费O(V),而不是O(logV),对吗?

有关空间复杂性的一个问题:为了比较队列Q中的顶点,我设计了一个具有距离的struct / class顶点作为一个成员,然后我实现了operator <等以通过比较它们的距离对顶点进行排序。 但似乎我必须定义一个重复数组dist []以便在Relax()中执行dist [v] = dist [u] + weight。 如果我没有定义重复数组,则必须查找v和u在队列Q中的位置,然后获取并检查它们的距离。 应该以这种方式工作吗? 也许我的执行不好?

除非您指定数据结构,否则 Dijkstra的算法(如您所写)不会具有运行时复杂性。 您以某种方式正确地说“第7行”涉及O(E)运算,但让我们看一下这些行(很幸运,Dijkstra很容易分析)。

  1. 初始化的意思是“给所有顶点一个无限的距离,除了源的距离为0。这很容易,可以在O(V)中完成。

  2. S有什么用处? 您将其“只写”使用。

  3. 您将所有元素放入队列。 这是龙。 什么是(优先级!)队列? 具有操作的数据结构,可以添加,可选地减少键(Dijkstra需要),移除(Dijkstra中不需要),extractMin。 根据实现,这些操作具有某些运行时。 例如,您可以构建一个只是(标记)集的哑PQ-然后在固定时间内添加和减少键,但是要提取最小值,则必须进行搜索。 Dijkstra中的规范解决方案是使用一个队列(如堆)来实现O(log n)中的所有相关操作。 让我们分析这种情况,尽管从技术上讲斐波那契堆会更好。 不要自己实现队列。 使用真正的PQ实现可以节省多少钱,这真是令人惊讶。

  4. 您经历了n次循环。

  5. 每次,您提取最小值,该最小值为O(n log n)总数(在所有迭代中)。

  6. S有什么用处?

  7. 您最多要遍历每个顶点的边缘一次,即,要对每个边缘进行两次韧化处理,因此总的来说,您可以完成循环O(E)次的所有操作。

  8. 放松意味着检查是否必须减小键并这样做。 我们已经知道,每个这样的操作都可以在队列(如果是堆)中添加O(log V),并且我们必须执行O(E)次,因此它是O(E log V),这占了整个运行时间。

如果您使用斐波那契堆,则可以降至O(VlogV + E),但这是学术性的。 实际的实现会调整堆。 如果您想了解实现的性能,请分析PQ操作。 但是正如我所说,如果您不完全知道自己在做什么,最好使用现有的实现。 您“在调用reduceKey之前先查找职位”的想法告诉我,在提出一个有效地使每个插入项占用O(V)(每次调用一次reduceKey进行排序)或O( V)每次提取的最小值(通过找到所需的最小值)。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM