Fibonacci heaps are proving tricky to understand - even though CLRS has made a really good attempt to make it understand how it works. But some questions are really unclear to me:
- Why would you choose a potential function like t + 2m? What is the reasoning ?
- What's the reasoning behind marking of nodes - I see that it is useful to put up nodes in root list etc. but why would you come up with such a scheme?
Thanks!
The reason for the choice of potential function has to do with a combination of different factors. Typically, the potential is chosen as t + 2m, where t is the number of trees and m is the number of marked nodes. We can analyze these pieces separately.
First, the potential function includes a t term because the delete-min step works by repeatedly merging together different trees in the linked list. The time required to do this depends on how many trees there are, and each iteration drops the number of trees down to a number that is roughly O(log n), where n is the number of nodes in the heap. By having the potential function include a t term, the work done to collapse all of the trees can be backcharged to earlier operations that added trees into this list in the first place.
The potential function includes an 2m term for a similar reason. When we call decrease-key, we cut the node from its parent and then mark the parent. If the parent was already marked, we cut it, then mark its parent as well. The amount of work done here is proportional to the length of the path we take as we keep cutting nodes, but then it unmarks all of the nodes involved. Consequently, if we have a potential function that takes the number of marked nodes into account, then we can say that while the single long series of cuts might be expensive, that work can be backcharged to earlier operations and spread out more evenly. The reason that this term is 2m rather than m is that as we drop the potential by decreasing the number of nodes that were cut, we're also increasing the t potential by adding more trees back into the linked list. By saying that each drop in a marked node decreases the potential by two, the net drop in potential from a cut is -1, so we can charge a future merge step to this decrease.
As for why we do marking at all - this is mostly to get the math to work out correctly when determining the number and size of trees that can remain in the Fibonacci heap. One can argue that this was the real genius step required to come up with the Fibonacci heap in the first place. Essentially, if you can cut too many children from each tree, then the heap loses its balance, and if you can't cut enough, then you can't efficiently implement decrease-key. Finding the balance of saying "you can lose one child" is a good compromise and makes the resulting math come out very nicely.
Hope this helps!