Skip to content

Commit a81c0c1

Browse files
author
Nikola Yurukov
committed
[Doc] Export priority and standardize documentation
1 parent 1f5e103 commit a81c0c1

File tree

4 files changed

+97
-99
lines changed

4 files changed

+97
-99
lines changed

fibheap/fibheap.go

Lines changed: 74 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -17,56 +17,54 @@ for the algorithm implementation.
1717
http://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+
*/
7068
package fibheap
7169

7270
import (
@@ -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.
8381
type 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.
149147
func NewFloatFibHeap() FloatingFibonacciHeap { return &fibHeap{nil, 0} }
150148

151149
func (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

278276
func (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

344342
func 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
}

fibheap/fibheap_examples_test.go

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ func ExampleFloatingFibonacciHeap_Enqueue() {
1515
// The function returns a pointer
1616
// to the node that contains the new value
1717
node := heap.Enqueue(SomeNumber)
18-
fmt.Println(node.priority)
18+
fmt.Println(node.Priority)
1919
// Output: 15.5
2020
}
2121

@@ -24,7 +24,7 @@ func ExampleFloatingFibonacciHeap_Min() {
2424
heap.Enqueue(SomeNumber)
2525
heap.Enqueue(SomeLargerNumber)
2626
min, _ := heap.Min()
27-
fmt.Println(min.priority)
27+
fmt.Println(min.Priority)
2828
// Output: 15.5
2929
}
3030

@@ -52,7 +52,7 @@ func ExampleFloatingFibonacciHeap_DequeueMin() {
5252
heap := NewFloatFibHeap()
5353
heap.Enqueue(SomeNumber)
5454
node, _ := heap.DequeueMin()
55-
fmt.Printf("Dequeueing minimal element: %v\n", node.priority)
55+
fmt.Printf("Dequeueing minimal element: %v\n", node.Priority)
5656
// Output:
5757
// Dequeueing minimal element: 15.5
5858
}
@@ -61,10 +61,10 @@ func ExampleFloatingFibonacciHeap_DecreaseKey() {
6161
heap := NewFloatFibHeap()
6262
node := heap.Enqueue(SomeNumber)
6363
min, _ := heap.Min()
64-
fmt.Printf("Minimal element before decreasing key: %v\n", min.priority)
64+
fmt.Printf("Minimal element before decreasing key: %v\n", min.Priority)
6565
heap.DecreaseKey(node, SomeSmallerNumber)
6666
min, _ = heap.Min()
67-
fmt.Printf("Minimal element after decreasing key: %v\n", min.priority)
67+
fmt.Printf("Minimal element after decreasing key: %v\n", min.Priority)
6868
// Output:
6969
// Minimal element before decreasing key: 15.5
7070
// Minimal element after decreasing key: -10.1
@@ -75,10 +75,10 @@ func ExampleFloatingFibonacciHeap_Delete() {
7575
node := heap.Enqueue(SomeNumber)
7676
heap.Enqueue(SomeLargerNumber)
7777
min, _ := heap.Min()
78-
fmt.Printf("Minimal element before deletion: %v\n", min.priority)
78+
fmt.Printf("Minimal element before deletion: %v\n", min.Priority)
7979
heap.Delete(node)
8080
min, _ = heap.Min()
81-
fmt.Printf("Minimal element after deletion: %v\n", min.priority)
81+
fmt.Printf("Minimal element after deletion: %v\n", min.Priority)
8282
// Output:
8383
// Minimal element before deletion: 15.5
8484
// Minimal element after deletion: 112.211
@@ -91,12 +91,12 @@ func ExampleFloatingFibonacciHeap_Merge() {
9191
heap1.Enqueue(SomeLargerNumber)
9292
heap2.Enqueue(SomeSmallerNumber)
9393
min, _ := heap1.Min()
94-
fmt.Printf("Minimal element of heap 1: %v\n", min.priority)
94+
fmt.Printf("Minimal element of heap 1: %v\n", min.Priority)
9595
min, _ = heap2.Min()
96-
fmt.Printf("Minimal element of heap 2: %v\n", min.priority)
96+
fmt.Printf("Minimal element of heap 2: %v\n", min.Priority)
9797
heap, _ := heap1.Merge(heap2)
9898
min, _ = heap.Min()
99-
fmt.Printf("Minimal element of merged heap: %v\n", min.priority)
99+
fmt.Printf("Minimal element of merged heap: %v\n", min.Priority)
100100
// Output:
101101
// Minimal element of heap 1: 15.5
102102
// Minimal element of heap 2: -10.1

fibheap/fibheap_single_example_test.go

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
package fibheap
22

3-
// Example Test for the Fibonacci heap with floats
3+
// Example usage of the Fibonacci heap
44

55
import (
66
"fmt"
@@ -15,15 +15,15 @@ func Example() {
1515
heap1 := NewFloatFibHeap()
1616
fmt.Println("Created heap 1.")
1717
nodeh1_1 := heap1.Enqueue(SomeLargerNumberAround15)
18-
fmt.Printf("Heap 1 insert: %v\n", nodeh1_1.priority)
18+
fmt.Printf("Heap 1 insert: %v\n", nodeh1_1.Priority)
1919

2020
heap2 := NewFloatFibHeap()
2121
fmt.Println("Created heap 2.")
2222
fmt.Printf("Heap 2 is empty? %v\n", heap2.IsEmpty())
2323
nodeh2_1 := heap2.Enqueue(SomeNumberAroundMinus1000)
24-
fmt.Printf("Heap 2 insert: %v\n", nodeh2_1.priority)
24+
fmt.Printf("Heap 2 insert: %v\n", nodeh2_1.Priority)
2525
nodeh2_2 := heap2.Enqueue(SomeNumberAround0)
26-
fmt.Printf("Heap 2 insert: %v\n", nodeh2_2.priority)
26+
fmt.Printf("Heap 2 insert: %v\n", nodeh2_2.Priority)
2727
fmt.Printf("Heap 1 size: %v\n", heap1.Size())
2828
fmt.Printf("Heap 2 size: %v\n", heap2.Size())
2929
fmt.Printf("Heap 1 is empty? %v\n", heap1.IsEmpty())
@@ -36,15 +36,15 @@ func Example() {
3636

3737
mergedHeap.DecreaseKey(nodeh2_1, SomeNumberAroundMinus1003)
3838
min, _ := mergedHeap.DequeueMin()
39-
fmt.Printf("Dequeue minimum of merged heap: %v\n", min.priority)
39+
fmt.Printf("Dequeue minimum of merged heap: %v\n", min.Priority)
4040
fmt.Printf("Merged heap size: %v\n", mergedHeap.Size())
4141

4242
fmt.Printf("Delete from merged heap: %v\n", SomeNumberAround0)
4343
mergedHeap.Delete(nodeh2_2)
4444
fmt.Printf("Merged heap size: %v\n", mergedHeap.Size())
4545

4646
min, _ = mergedHeap.DequeueMin()
47-
fmt.Printf("Extracting minimum of merged heap: %v\n", min.priority)
47+
fmt.Printf("Extracting minimum of merged heap: %v\n", min.Priority)
4848
fmt.Printf("Merged heap size: %v\n", mergedHeap.Size())
4949
fmt.Printf("Merged heap is empty? %v\n", mergedHeap.IsEmpty())
5050

fibheap/fibheap_test.go

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -134,16 +134,16 @@ func TestEnqueueDequeueMin(t *testing.T) {
134134
min, err = heap.DequeueMin()
135135
assert.NoError(t, err)
136136
if heap.Size() == 199 {
137-
assert.Equal(t, Seq1FirstMinimum, min.priority)
137+
assert.Equal(t, Seq1FirstMinimum, min.Priority)
138138
}
139139
if heap.Size() == 197 {
140-
assert.Equal(t, Seq1ThirdMinimum, min.priority)
140+
assert.Equal(t, Seq1ThirdMinimum, min.Priority)
141141
}
142142
if heap.Size() == 195 {
143-
assert.Equal(t, Seq1FifthMinimum, min.priority)
143+
assert.Equal(t, Seq1FifthMinimum, min.Priority)
144144
}
145145
if heap.Size() == 0 {
146-
assert.Equal(t, Seq1LastMinimum, min.priority)
146+
assert.Equal(t, Seq1LastMinimum, min.Priority)
147147
}
148148
}
149149
}
@@ -176,7 +176,7 @@ func TestEnqueueDecreaseKey(t *testing.T) {
176176
for i := 0; i < len(NumberSequence2Sorted); i++ {
177177
min, err = heap.DequeueMin()
178178
assert.NoError(t, err)
179-
assert.Equal(t, NumberSequence2Sorted[i], min.priority)
179+
assert.Equal(t, NumberSequence2Sorted[i], min.Priority)
180180
}
181181
}
182182

@@ -209,7 +209,7 @@ func TestEnqueueDelete(t *testing.T) {
209209
for i := 0; i < len(NumberSequence2Deleted3ElemSorted); i++ {
210210
min, err = heap.DequeueMin()
211211
assert.NoError(t, err)
212-
assert.Equal(t, NumberSequence2Deleted3ElemSorted[i], min.priority)
212+
assert.Equal(t, NumberSequence2Deleted3ElemSorted[i], min.Priority)
213213
}
214214
}
215215

@@ -231,7 +231,7 @@ func TestMerge(t *testing.T) {
231231
for i := 0; i < len(NumberSequenceMerged3And4Sorted); i++ {
232232
min, err = heap.DequeueMin()
233233
assert.NoError(t, err)
234-
assert.Equal(t, NumberSequenceMerged3And4Sorted[i], min.priority)
234+
assert.Equal(t, NumberSequenceMerged3And4Sorted[i], min.Priority)
235235
}
236236
}
237237

0 commit comments

Comments
 (0)