- 每个顶点可以连接到(V-1)个顶点,因此每个顶点的相邻边数为V-1。假设E表示与每个顶点相连的V-1条边。
- 在最小堆中查找和更新每个相邻顶点的权重是O(log(V)) + O(1),即
O(log(V))
。 - 因此从步骤1和步骤2可知,更新一个顶点的所有相邻顶点的时间复杂度为E*(logV),或者
E*logV
。 - 因此所有V个顶点的时间复杂度为V*(E*logV),即
O(VElogV)
。
但是Dijkstra算法的时间复杂度为O(ElogV)。为什么?
O(log(V))
。E*logV
。O(VElogV)
。但是Dijkstra算法的时间复杂度为O(ElogV)。为什么?
Dijkstra最短路径算法的时间复杂度是O(ElogV)
,其中:
V
表示顶点数E
表示边的总数你的分析是正确的,但符号的含义有所不同!你说算法的时间复杂度是O(VElogV)
,其中:
V
表示顶点数E
表示单个节点连接的最大边数。让我们把你的E
重新命名为N
。因此,一个分析说O(ElogV)
,另一个分析说O(VNlogV)
。两者都是正确的,实际上E=O(VN)
。区别在于ElogV
是更紧密的估计。
为了更好地解释,我会提供更加详细的说明:
O(
对于每个顶点使用最小堆: 对于每条边线性地: 推送与该边指向的顶点相关的顶点到最小堆中)
V
= 顶点的数量O(V * (
从最小堆中弹出顶点 +
找到边中未访问的顶点并将它们推入最小堆*
))
E
= 每个顶点上的边的数量O(V * (
从最小堆中弹出顶点 +
E
*
将未访问的顶点推入最小堆))
。请注意,在“访问”节点之前我们可以多次推入同一节点。O(V * (log(
堆大小) + E * log(
堆大小)))
O(V * ((E + 1) * log(
堆大小)))
O(V * (E * log(
堆大小)))
E = V
因为每个顶点都可以引用所有其他顶点O(V * (V * log(
堆大小)))
O(V^2 * log(
堆大小))
V^2
,因为我们每次想要更新距离时都要推入堆中,并且对于每个顶点最多可以有 V 次比较。例如,对于最后一个顶点,第一个顶点距离为 10
,第二个为 9
,第三个为 8
,等等,因此我们每次都会推入来进行更新。O(V^2 * log(V^2))
O(V^2 * 2 * log(V))
O(V^2 * log(V))
V^2
也是边的总数,所以如果我们令E = V^2
(正式命名中的),我们将得到O(E * log(V))
O(V^2 * log(V^2))
简化为 O(E*log(V))
而不是 O(E*log(E))
,这是否有原因?我理解背后的数学,但不理解推理。 - LPRO(E*log(E))
也是正确的,但O(E*log(V))
更精确。而且OP特别询问了O(E*log(V))
,所以在这种情况下我们必须使用它。 - Sam设n为顶点数量,m为边的数量。
使用Dijkstra算法时,由于需要进行O(n)次delete-min以及O(m)次decrease_key操作,每次操作时间复杂度均为O(logn),因此使用二叉堆的总运行时间为O(log(n)(m + n))。使用斐波那契堆可以将decrease_key操作的摊销成O(1),从而使得总运行时间为O(nlogn+m),但实践中通常不这样做,因为斐波那契堆的常数因子惩罚非常大,在随机图上decrease_key操作的次数远低于其上限(在稀疏图中约为O(n*log(m/n))),因此总运行时间既取决于数据结构,也取决于输入类型。
在稠密(或完全)图中,E logV > V^2
。
使用链接数据和二进制堆并不总是最好的选择。
在这种情况下,我更喜欢仅使用矩阵数据并通过行节省最小长度。
只需要V^2
的时间。
如果E < V / logV
,或者每个顶点的最大边数小于某个常数K
,则使用二叉堆。
E
代表边,V
代表顶点。边的数量为
(V *(V-1)) / 2
大约
V ^ 2
因此,我们可以将最大的V ^ 2
边添加到最小堆中。 因此,对最小堆中的元素进行排序需要
O(Log(V ^ 2))
每次我们将新元素插入最小堆时,都会进行排序。 我们将有E
条边,因此我们将进行E
次排序。 因此总时间复杂度为
O(E * Log(V ^ 2)= O( 2 * E * Log(V))
O( E * Log(V))
maxAdjacentEdgesOfAVertex * totalVertices >= totalEdges
就是使得上限更紧的因素。更紧的上限意味着更接近真实值的估计。例如,如果一个算法执行了n + 10
次操作,你可以说它是O(n^2)
是正确的,或者是O(nlogn)
也是正确的。但比这两个更紧的上限是O(n)
。最紧密的上限被称为Θ
,因此在上述示例中,n + 1 = Θ(n)
。(Θ
的定义是既是上限又是下限) - Shahbazlog
函数,因此基数2有点被隐含了。 (看到我做的了吗?) - ShahbazO(E log V)
假设给定的图是连通的。例如,在有很多孤立顶点的稀疏图的情况下,它将不成立。这就是为什么 Dijkstra 的二叉堆实现的最坏情况是O(V log V + E log V)
。当我们不能假设E >= V
时,它不能被降低到O(E log V)
。 - DBedrenko