问题
Tim Roughgarden in Algorithms 2 course teaches the following approach for updating the adjacent vertices in the min heap (after extracting min from the heap):
When a vertice v is added to the MST:
For each edge (v,w) in the unexplored tree:
1. Delete w from the min heap.
2. Recompute the key[w] (i.e. it's value from the unexplored tree
to the explored one).
3. Add the value back to the heap.
So, basically this involves deletion from the heap (and heapify which takes O(logn)) and then reinserting (again O(logn))
Instead, if I use the following approach:
For each edge (v,w) in the unexplored tree:
1. Get the position of the node in the heap(array) using HashMap -> O(1)
2. Update the value in place.
3. Bubble up or bubble down accordingly. -> O(logn)
Although they're the same asymptotically, the latter one gives better constants. So is it better than the one in the course? Or am I missing something?
回答1:
It is asymptotically the same, and you would get a better constant factor with a high probability. What you try to achieve with HashMap uses O(n) extra space. Also, in worst case, it takes O(logn) extra time, same as a remove from heap would cost. However, its probability of taking time proportional to logn is really low. You may look into a probabilistic performance analysis of particular HashMap implementation you intend to use. if you're interested in figuring out more about that.
I could propose a better solution that avoids usage of HashMap, and is consequently easier to observe/analyze constant factor due not not requiring probabilistic analysis.
The solution is storing the key values in an external array A and overriding the comparison function of the heap so that it compares the elements inside it based on their corresponding values which are stored in A.
In other words, the default comparison function in many heap implementations are as follows.
function compare(a, b):
return a < b
While updating it, you will change it to:
function compare(a, b):
return A[a] < A[b]
In array A, each vertex v will have a corresponding cell, causing O(n) extra space usage, just like your HashMap idea. But updating that value upon adding v to discovered nodes will take O(1) time even in the worst case.
It may not be possible to make this update based on the programming language you implement in and libraries you use for heap, but it is possible in many languages and languages including and not limited to C++'s std::priority_queue of STL. You may implement this with a custom implementation of heap as well, if experimenting with such a custom data structure is what you're after.
来源:https://stackoverflow.com/questions/36214250/maintaining-invariant-in-prims-algorithm