@@ -17,56 +17,54 @@ for the algorithm implementation.
1717http://www.keithschwarz.com/interesting/code/?dir=fibonacci-heap
1818*/
1919
20- /*
21- * An implementation of a priority queue backed by a Fibonacci heap,
22- * as described by Fredman and Tarjan. Fibonacci heaps are interesting
23- * theoretically because they have asymptotically good runtime guarantees
24- * for many operations. In particular, insert, peek, and decrease-key all
25- * run in amortized O(1) time. dequeueMin and delete each run in amortized
26- * O(lg n) time. This allows algorithms that rely heavily on decrease-key
27- * to gain significant performance boosts. For example, Dijkstra's algorithm
28- * for single-source shortest paths can be shown to run in O(m + n lg n) using
29- * a Fibonacci heap, compared to O(m lg n) using a standard binary or binomial
30- * heap.
31- *
32- * Internally, a Fibonacci heap is represented as a circular, doubly-linked
33- * list of trees obeying the min-heap property. Each node stores pointers
34- * to its parent (if any) and some arbitrary child. Additionally, every
35- * node stores its degree (the number of children it has) and whether it
36- * is a "marked" node. Finally, each Fibonacci heap stores a pointer to
37- * the tree with the minimum value.
38- *
39- * To insert a node into a Fibonacci heap, a singleton tree is created and
40- * merged into the rest of the trees. The merge operation works by simply
41- * splicing together the doubly-linked lists of the two trees, then updating
42- * the min pointer to be the smaller of the minima of the two heaps. Peeking
43- * at the smallest element can therefore be accomplished by just looking at
44- * the min element. All of these operations complete in O(1) time.
45- *
46- * The tricky operations are dequeueMin and decreaseKey. dequeueMin works
47- * by removing the root of the tree containing the smallest element, then
48- * merging its children with the topmost roots. Then, the roots are scanned
49- * and merged so that there is only one tree of each degree in the root list.
50- * This works by maintaining a dynamic array of trees, each initially null,
51- * pointing to the roots of trees of each dimension. The list is then scanned
52- * and this array is populated. Whenever a conflict is discovered, the
53- * appropriate trees are merged together until no more conflicts exist. The
54- * resulting trees are then put into the root list. A clever analysis using
55- * the potential method can be used to show that the amortized cost of this
56- * operation is O(lg n), see "Introduction to Algorithms, Second Edition" by
57- * Cormen, Rivest, Leiserson, and Stein for more details.
58- *
59- * The other hard operation is decreaseKey, which works as follows. First, we
60- * update the key of the node to be the new value. If this leaves the node
61- * smaller than its parent, we're done. Otherwise, we cut the node from its
62- * parent, add it as a root, and then mark its parent. If the parent was
63- * already marked, we cut that node as well, recursively mark its parent,
64- * and continue this process. This can be shown to run in O(1) amortized time
65- * using yet another clever potential function. Finally, given this function,
66- * we can implement delete by decreasing a key to -\infty, then calling
67- * dequeueMin to extract it.
68- */
69-
20+ /*Package fibheap is an implementation of a priority queue backed by a Fibonacci heap,
21+ as described by Fredman and Tarjan. Fibonacci heaps are interesting
22+ theoretically because they have asymptotically good runtime guarantees
23+ for many operations. In particular, insert, peek, and decrease-key all
24+ run in amortized O(1) time. dequeueMin and delete each run in amortized
25+ O(lg n) time. This allows algorithms that rely heavily on decrease-key
26+ to gain significant performance boosts. For example, Dijkstra's algorithm
27+ for single-source shortest paths can be shown to run in O(m + n lg n) using
28+ a Fibonacci heap, compared to O(m lg n) using a standard binary or binomial
29+ heap.
30+
31+ Internally, a Fibonacci heap is represented as a circular, doubly-linked
32+ list of trees obeying the min-heap property. Each node stores pointers
33+ to its parent (if any) and some arbitrary child. Additionally, every
34+ node stores its degree (the number of children it has) and whether it
35+ is a "marked" node. Finally, each Fibonacci heap stores a pointer to
36+ the tree with the minimum value.
37+
38+ To insert a node into a Fibonacci heap, a singleton tree is created and
39+ merged into the rest of the trees. The merge operation works by simply
40+ splicing together the doubly-linked lists of the two trees, then updating
41+ the min pointer to be the smaller of the minima of the two heaps. Peeking
42+ at the smallest element can therefore be accomplished by just looking at
43+ the min element. All of these operations complete in O(1) time.
44+
45+ The tricky operations are dequeueMin and decreaseKey. dequeueMin works
46+ by removing the root of the tree containing the smallest element, then
47+ merging its children with the topmost roots. Then, the roots are scanned
48+ and merged so that there is only one tree of each degree in the root list.
49+ This works by maintaining a dynamic array of trees, each initially null,
50+ pointing to the roots of trees of each dimension. The list is then scanned
51+ and this array is populated. Whenever a conflict is discovered, the
52+ appropriate trees are merged together until no more conflicts exist. The
53+ resulting trees are then put into the root list. A clever analysis using
54+ the potential method can be used to show that the amortized cost of this
55+ operation is O(lg n), see "Introduction to Algorithms, Second Edition" by
56+ Cormen, Rivest, Leiserson, and Stein for more details.
57+
58+ The other hard operation is decreaseKey, which works as follows. First, we
59+ update the key of the node to be the new value. If this leaves the node
60+ smaller than its parent, we're done. Otherwise, we cut the node from its
61+ parent, add it as a root, and then mark its parent. If the parent was
62+ already marked, we cut that node as well, recursively mark its parent,
63+ and continue this process. This can be shown to run in O(1) amortized time
64+ using yet another clever potential function. Finally, given this function,
65+ we can implement delete by decreasing a key to -\infty, then calling
66+ dequeueMin to extract it.
67+ */
7068package fibheap
7169
7270import (
@@ -78,27 +76,28 @@ import (
7876 ************** INTERFACE *****************
7977 ******************************************/
8078
81- // The FloatingFibonacciHeap is an implementation of a fibonacci heap
79+ // FloatingFibonacciHeap is an implementation of a fibonacci heap
8280// with only floating-point priorities and no user data attached.
8381type FloatingFibonacciHeap interface {
84- // Adds and element to the heap
82+ // Enqueue adds and element to the heap
8583 Enqueue (priority float64 ) * Entry
86- // Returns the minimum element in the heap
84+ // Min returns the minimum element in the heap
8785 Min () (* Entry , error )
88- // Is the heap empty?
86+ // IsEmpty answers: is the heap empty?
8987 IsEmpty () bool
90- // The number of elements in the heap
88+ // Size gives the number of elements in the heap
9189 Size () uint
92- // Removes and returns the minimal element
93- // in the heap
90+ // DequeueMin removes and returns the
91+ // minimal element in the heap
9492 DequeueMin () (* Entry , error )
95- // Decreases the key of the given element
96- // and sets it to the new given priority
97- // returns the node if succesfully set
93+ // DecreaseKey decreases the key of the
94+ // given element, sets it to the new
95+ // given priority and returns the node
96+ // if successfully set
9897 DecreaseKey (node * Entry , newPriority float64 ) (* Entry , error )
99- // Deletes the given element in the heap
98+ // Delete deletes the given element in the heap
10099 Delete (node * Entry ) error
101- // Will merge two heaps
100+ // Merge merges two heaps
102101 Merge (otherHeap FloatingFibonacciHeap ) (FloatingFibonacciHeap , error )
103102}
104103
@@ -108,7 +107,8 @@ type Entry struct {
108107 degree int
109108 marked bool
110109 next , prev , child , parent * Entry
111- priority float64
110+ // Priority is the numerical priority of the node
111+ Priority float64
112112}
113113
114114/******************************************
@@ -132,20 +132,18 @@ func newEntry(priority float64) *Entry {
132132 result .parent = nil
133133 result .next = result
134134 result .prev = result
135- result .priority = priority
135+ result .Priority = priority
136136 return result
137137}
138138
139139// ***********
140140// ACTUAL CODE
141141// ***********
142142
143- /*
144- NewFloatFibHeap creates a new, empty, Fibonacci heap object .
143+ // Remember that it's actually *fibHeap and not fibHeap
144+ // that fulfills the contract of the interface .
145145
146- Remember that it's actually *fibHeap and not fibHeap
147- that fulfills the contract of the interface.
148- */
146+ // NewFloatFibHeap creates a new, empty, Fibonacci heap object.
149147func NewFloatFibHeap () FloatingFibonacciHeap { return & fibHeap {nil , 0 } }
150148
151149func (heap * fibHeap ) Enqueue (priority float64 ) * Entry {
@@ -229,7 +227,7 @@ func (heap *fibHeap) DequeueMin() (*Entry, error) {
229227
230228 // Determine which of two trees has the smaller root
231229 var minT , maxT * Entry
232- if other .priority < curr .priority {
230+ if other .Priority < curr .Priority {
233231 minT = other
234232 maxT = curr
235233 } else {
@@ -266,7 +264,7 @@ func (heap *fibHeap) DequeueMin() (*Entry, error) {
266264 * priority, we need to make sure that the min pointer points to
267265 * the root-level one.
268266 */
269- if curr .priority <= heap .min .priority {
267+ if curr .Priority <= heap .min .Priority {
270268 heap .min = curr
271269 }
272270 }
@@ -277,7 +275,7 @@ func (heap *fibHeap) DequeueMin() (*Entry, error) {
277275
278276func (heap * fibHeap ) DecreaseKey (node * Entry , newPriority float64 ) (* Entry , error ) {
279277
280- if newPriority > node .priority {
278+ if newPriority > node .Priority {
281279 return nil , fmt .Errorf ("The given new priority is larger than the old" )
282280 }
283281
@@ -334,21 +332,21 @@ func mergeLists(one, two *Entry) *Entry {
334332 two .next = oneNext
335333 two .next .prev = two
336334
337- if one .priority < two .priority {
335+ if one .Priority < two .Priority {
338336 return one
339337 }
340338 return two
341339
342340}
343341
344342func decreaseKeyUnchecked (heap * fibHeap , node * Entry , priority float64 ) {
345- node .priority = priority
343+ node .Priority = priority
346344
347- if node .parent != nil && node .priority <= node .parent .priority {
345+ if node .parent != nil && node .Priority <= node .parent .Priority {
348346 cutNode (heap , node )
349347 }
350348
351- if node .priority <= heap .min .priority {
349+ if node .Priority <= heap .min .Priority {
352350 heap .min = node
353351 }
354352}
0 commit comments