简体   繁体   English

使用优先队列的 Prims 算法的复杂性?

[英]Complexity of Prims Algorithm using Priority Queue?

I am using an adjacency matrix, priority queue is the data structure.我正在使用邻接矩阵,优先级队列是数据结构。

By my calculation, complexity is V^3 log V :根据我的计算,复杂度是V^3 log V

  • While loop: V While 循环: V
  • Checking adjacent Vertices: V检查相邻顶点: V
  • Checking the queue if the entry is already present, and updating the same: V log v如果条目已经存在,则检查队列并更新: V log v

But, I read everywhere that the complexity is V^2但是,我到处都读到复杂度是V^2

Please explain.请解释。

If you use a Fibonacci heap, then extracting the min is O(lg V) amortized cost and updating an entry in it is O(1) amortized.如果您使用斐波那契堆,则提取最小值是O(lg V)摊销成本,更新其中的条目是O(1)摊销成本。

If we use this pseudo code如果我们使用这个伪代码

while priorityQueue not empty
    u = priorityQueue.exractMin()
    for each v in u.adjacencies
        if priorityQueue.contains(v) and needsWeightReduction(u, v)
            priorityQueue.updateKeyWeight(u, v)

Assume that the implementation has constant time for both priorityQueue.contains(v) and needsWeightReduction(u, v) .假设实现对于priorityQueue.contains(v)needsWeightReduction(u, v)都有固定的时间。

Something to note is that you can bound slightly tighter for checking adjacencies.需要注意的是,您可以稍微更紧地检查邻接关系。 While the outer loop runs V times, and checking the adjacencies of any single node is at worst V operations, you can use aggregate analysis to realize that you will never check for more than E adjacencies(because theres only E edges).虽然外部循环运行V次,并且检查任何单个节点的邻接关系是最坏的V操作,但您可以使用聚合分析来意识到您永远不会检查超过E邻接关系(因为只有 E 边缘)。 And E <= V^2 , so this is a slightly better bound.E <= V^2 ,所以这是一个更好的界限。

So, you have the outer loop V times, and the inner loop E times.所以,你有外循环 V 次,内循环 E 次。 Extracting the min runs V times, and updating an entry in the heap runs E times.提取最小值运行V次,更新堆中的条目运行E次。

  V*lgV + E*1
= O(V lgV + E)

Again, since E <= V^2 you could use this fact to substitute and get同样,由于E <= V^2你可以使用这个事实来替代并得到

  O(V lgV + V^2)
= O(V^2)

But this is a looser bound when considering sparse graphs(although correct).但在考虑稀疏图时,这是一个更宽松的界限(尽管是正确的)。

Using a min heap-based priority queue, the time complexity is O(ElogV).使用基于最小堆的优先级队列,时间复杂度为 O(ElogV)。

As you said, the outer while loop is O(V) because it is looping through every vertex since each one needs to be added to the MST once.正如您所说,外部 while 循环是 O(V),因为它遍历每个顶点,因为每个顶点都需要添加到 MST 一次。

For each vertex considered in the while loop, the following two steps need to happen:对于 while 循环中考虑的每个顶点,需要执行以下两个步骤:

  1. The next edge is chosen to add to the MST.选择下一条边添加到 MST。 According to the properties of a min heap-based priority queue, the root element will always be the smallest element.根据基于最小堆的优先级队列的属性,根元素总是最小的元素。 Therefore choosing the next edge, the one with the lowest cost, will be an O(1) extraction of the root element.因此,选择下一个边,即成本最低的边,将是对根元素的 O(1) 提取。 The remaining values will need to be shifted after the extraction in a way that maintains the priority queue.提取后剩余的值需要以维持优先级队列的方式移动。 Since the queue represents a balanced binary tree, this shift can happen in O(logV) in the worst case.由于队列表示平衡二叉树,因此在最坏的情况下,这种偏移可能会在 O(logV) 内发生。

  2. The priority queue is updated.更新优先级队列。 Edges incident to the new vertex may need to have their costs updated in the queue because we will now consider the costs associated with the edges between the newly added vertex and its neighbors (however, if they neighbored a previously added vertex through an edge with a lower cost than the newly introduced edge, the cost will not be updated because we are looking for the minimum costs).与新顶点相关的边可能需要在队列中更新它们的成本,因为我们现在将考虑与新添加的顶点及其邻居之间的边相关的成本(但是,如果它们通过一条边与先前添加的顶点相邻)成本低于新引入的边缘,成本不会更新,因为我们正在寻找最低成本)。 Again this will be O(logV) because in the worst case, a vertex will need to be shifted through the entire length of the balanced binary tree that represents the queue.这也是 O(logV),因为在最坏的情况下,一个顶点需要在代表队列的平衡二叉树的整个长度上移动。

Step 1 happens V times because it occurs once in the while loop, so it is O(VlogV) total, and step 2 happens E times in the worst case where every edge is attached to the current vertex and therefore they all need to be updated, which means it is O(ElogV) total.步骤 1 发生 V 次,因为它在 while 循环中发生一次,所以总共是 O(VlogV),步骤 2 在最坏的情况下发生 E 次,其中每条边都连接到当前顶点,因此它们都需要更新,这意味着它是 O(ElogV) 总数。 The set-up is O(E) because it requires initializing each edge cost in the priority queue to be infinity.设置是 O(E),因为它需要将优先级队列中的每个边成本初始化为无穷大。

Total time complexity using a min heap based priroty queue = O(E + VlogV + ElogV) = O(ElogV)使用基于最小堆的优先级队列的总时间复杂度 = O(E + VlogV + ElogV) = O(ElogV)

When you're reading that the complexity is O(V^2), you might be looking at implementations that don't use heaps.当您阅读复杂度为 O(V^2) 时,您可能正在查看不使用堆的实现。 In this case, the outer while loop is still O(V).在这种情况下,外部 while 循环仍然是 O(V)。 The bottleneck is in the step that chooses the next vertex to add to the MST, which is O(V) because you'll need to check the cost associated every neighboring node to find the lowest cost, which in the worst case means checking all other nodes.瓶颈在于选择要添加到 MST 的下一个顶点的步骤,即 O(V),因为您需要检查与每个相邻节点相关的成本以找到最低成本,这在最坏的情况下意味着检查所有其他节点。 Therefore the complexity is O(V*V) = O(V^2).因此复杂度为 O(V*V) = O(V^2)。

Additionally, O(ElogV) in very dense graphs becomes O(V^2) because in any graph there can be a maximum of E = V^2 total edges.此外,在非常密集的图中,O(ElogV) 变为 O(V^2),因为在任何图中,最多可以有 E = V^2 个总边。

如果不使用优先级队列,则使用二叉堆它包括两个基本步骤: 1.Insertion 使用插入排序算法的插入时间复杂度在最坏情况下为 O(E^2) 2.Deletion 删除每个出队需要 O(1) 并且dequeue 相当于顶点数,如果使用映射,否则将几乎相同所以,这里的总时间复杂度是 O(V+E^2)

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

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