Question

I am using an adjacency matrix, priority queue is the data structure.

By my calculation, complexity is V^3 log V:

  • While loop: V
  • Checking adjacent Vertices: V
  • Checking the queue if the entry is already present, and updating the same: V log v

But, I read everywhere that the complexity is V^2

Please explain.

Was it helpful?

Solution

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.

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).

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). And E <= V^2, so this is a slightly better bound.

So, you have the outer loop V times, and the inner loop E times. Extracting the min runs V times, and updating an entry in the heap runs E times.

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

Again, since E <= V^2 you could use this fact to substitute and get

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

But this is a looser bound when considering sparse graphs(although correct).

OTHER TIPS

Using a min heap-based priority queue, the time complexity is 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.

For each vertex considered in the while loop, the following two steps need to happen:

  1. The next edge is chosen to add to the 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. 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.

  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.

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. The set-up is O(E) because it requires initializing each edge cost in the priority queue to be infinity.

Total time complexity using a min heap based priroty queue = 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. In this case, the outer while loop is still 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. Therefore the complexity is 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.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top