Skip to content

Commit b5cf6ee

Browse files
author
Nikola Yurukov
committed
[Dev] Fibonacci Heap: Return struct, not interface
1 parent 0a20274 commit b5cf6ee

File tree

4 files changed

+61
-89
lines changed

4 files changed

+61
-89
lines changed

fibheap/fibheap.go

Lines changed: 56 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -78,27 +78,9 @@ import (
7878

7979
// FloatingFibonacciHeap is an implementation of a fibonacci heap
8080
// with only floating-point priorities and no user data attached.
81-
type FloatingFibonacciHeap interface {
82-
// Enqueue adds and element to the heap
83-
Enqueue(priority float64) *Entry
84-
// Min returns the minimum element in the heap
85-
Min() (*Entry, error)
86-
// IsEmpty answers: is the heap empty?
87-
IsEmpty() bool
88-
// Size gives the number of elements in the heap
89-
Size() uint
90-
// DequeueMin removes and returns the
91-
// minimal element in the heap
92-
DequeueMin() (*Entry, error)
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
97-
DecreaseKey(node *Entry, newPriority float64) (*Entry, error)
98-
// Delete deletes the given element in the heap
99-
Delete(node *Entry) error
100-
// Merge merges two heaps
101-
Merge(otherHeap FloatingFibonacciHeap) (FloatingFibonacciHeap, error)
81+
type FloatingFibonacciHeap struct {
82+
min *Entry // The minimal element
83+
size uint // Size of the heap
10284
}
10385

10486
// Entry is the entry type that will be used
@@ -111,42 +93,11 @@ type Entry struct {
11193
Priority float64
11294
}
11395

114-
/******************************************
115-
************** END INTERFACE *************
116-
******************************************/
117-
118-
type fibHeap struct {
119-
min *Entry // The minimal element
120-
size uint // Size of the heap
121-
}
122-
123-
// ****************
124-
// HELPER FUNCTIONS
125-
// ****************
126-
127-
func newEntry(priority float64) *Entry {
128-
result := new(Entry)
129-
result.degree = 0
130-
result.marked = false
131-
result.child = nil
132-
result.parent = nil
133-
result.next = result
134-
result.prev = result
135-
result.Priority = priority
136-
return result
137-
}
138-
139-
// ***********
140-
// ACTUAL CODE
141-
// ***********
142-
143-
// Remember that it's actually *fibHeap and not fibHeap
144-
// that fulfills the contract of the interface.
145-
14696
// NewFloatFibHeap creates a new, empty, Fibonacci heap object.
147-
func NewFloatFibHeap() FloatingFibonacciHeap { return &fibHeap{nil, 0} }
97+
func NewFloatFibHeap() FloatingFibonacciHeap { return FloatingFibonacciHeap{nil, 0} }
14898

149-
func (heap *fibHeap) Enqueue(priority float64) *Entry {
99+
// Enqueue adds and element to the heap
100+
func (heap *FloatingFibonacciHeap) Enqueue(priority float64) *Entry {
150101
singleton := newEntry(priority)
151102

152103
// Merge singleton list with heap
@@ -155,22 +106,27 @@ func (heap *fibHeap) Enqueue(priority float64) *Entry {
155106
return singleton
156107
}
157108

158-
func (heap *fibHeap) Min() (*Entry, error) {
109+
// Min returns the minimum element in the heap
110+
func (heap *FloatingFibonacciHeap) Min() (*Entry, error) {
159111
if heap.IsEmpty() {
160112
return nil, fmt.Errorf("Trying to get minimum element of empty heap")
161113
}
162114
return heap.min, nil
163115
}
164116

165-
func (heap *fibHeap) IsEmpty() bool {
117+
// IsEmpty answers: is the heap empty?
118+
func (heap *FloatingFibonacciHeap) IsEmpty() bool {
166119
return heap.size == 0
167120
}
168121

169-
func (heap *fibHeap) Size() uint {
122+
// Size gives the number of elements in the heap
123+
func (heap *FloatingFibonacciHeap) Size() uint {
170124
return heap.size
171125
}
172126

173-
func (heap *fibHeap) DequeueMin() (*Entry, error) {
127+
// DequeueMin removes and returns the
128+
// minimal element in the heap
129+
func (heap *FloatingFibonacciHeap) DequeueMin() (*Entry, error) {
174130
if heap.IsEmpty() {
175131
return nil, fmt.Errorf("Cannot dequeue minimum of empty heap")
176132
}
@@ -273,7 +229,11 @@ func (heap *fibHeap) DequeueMin() (*Entry, error) {
273229
return min, nil
274230
}
275231

276-
func (heap *fibHeap) DecreaseKey(node *Entry, newPriority float64) (*Entry, error) {
232+
// DecreaseKey decreases the key of the
233+
// given element, sets it to the new
234+
// given priority and returns the node
235+
// if successfully set
236+
func (heap *FloatingFibonacciHeap) DecreaseKey(node *Entry, newPriority float64) (*Entry, error) {
277237

278238
if heap.IsEmpty() {
279239
return nil, fmt.Errorf("Cannot decrease key in an empty heap")
@@ -292,7 +252,8 @@ func (heap *fibHeap) DecreaseKey(node *Entry, newPriority float64) (*Entry, erro
292252
return node, nil
293253
}
294254

295-
func (heap *fibHeap) Delete(node *Entry) error {
255+
// Delete deletes the given element in the heap
256+
func (heap *FloatingFibonacciHeap) Delete(node *Entry) error {
296257

297258
if heap.IsEmpty() {
298259
return fmt.Errorf("Cannot delete element from an empty heap")
@@ -307,36 +268,47 @@ func (heap *fibHeap) Delete(node *Entry) error {
307268
return nil
308269
}
309270

310-
/*
311-
* Given two Fibonacci heaps, returns a new Fibonacci heap that contains
312-
* all of the elements of the two heaps. Each of the input heaps is
313-
* destructively modified by having all its elements removed. You can
314-
* continue to use those heaps, but be aware that they will be empty
315-
* after this call completes.
316-
*/
317-
func (heap *fibHeap) Merge(other FloatingFibonacciHeap) (FloatingFibonacciHeap, error) {
271+
// Merge returns a new Fibonacci heap that contains
272+
// all of the elements of the two heaps. Each of the input heaps is
273+
// destructively modified by having all its elements removed. You can
274+
// continue to use those heaps, but be aware that they will be empty
275+
// after this call completes.
276+
func (heap *FloatingFibonacciHeap) Merge(other *FloatingFibonacciHeap) (FloatingFibonacciHeap, error) {
318277

319278
if heap == nil || other == nil {
320-
return nil, fmt.Errorf("One of the heaps to merge is nil. Cannot merge")
279+
return FloatingFibonacciHeap{}, fmt.Errorf("One of the heaps to merge is nil. Cannot merge")
321280
}
322281

323-
otherHeap, ok := other.(*fibHeap)
324-
if !ok {
325-
// throw an error
326-
return nil, fmt.Errorf("The passed object is of type %T, not of internal type *fibHeap. "+
327-
"Please provide your own implementation of merge", other)
328-
}
282+
resultSize := heap.size + other.size
329283

330-
resultSize := heap.size + otherHeap.size
331-
332-
resultMin := mergeLists(heap.min, otherHeap.min)
284+
resultMin := mergeLists(heap.min, other.min)
333285

334286
heap.min = nil
335-
otherHeap.min = nil
287+
other.min = nil
336288
heap.size = 0
337-
otherHeap.size = 0
289+
other.size = 0
290+
291+
return FloatingFibonacciHeap{resultMin, resultSize}, nil
292+
}
338293

339-
return &fibHeap{resultMin, resultSize}, nil
294+
/******************************************
295+
************** END INTERFACE *************
296+
******************************************/
297+
298+
// ****************
299+
// HELPER FUNCTIONS
300+
// ****************
301+
302+
func newEntry(priority float64) *Entry {
303+
result := new(Entry)
304+
result.degree = 0
305+
result.marked = false
306+
result.child = nil
307+
result.parent = nil
308+
result.next = result
309+
result.prev = result
310+
result.Priority = priority
311+
return result
340312
}
341313

342314
func mergeLists(one, two *Entry) *Entry {
@@ -361,7 +333,7 @@ func mergeLists(one, two *Entry) *Entry {
361333

362334
}
363335

364-
func decreaseKeyUnchecked(heap *fibHeap, node *Entry, priority float64) {
336+
func decreaseKeyUnchecked(heap *FloatingFibonacciHeap, node *Entry, priority float64) {
365337
node.Priority = priority
366338

367339
if node.parent != nil && node.Priority <= node.parent.Priority {
@@ -373,7 +345,7 @@ func decreaseKeyUnchecked(heap *fibHeap, node *Entry, priority float64) {
373345
}
374346
}
375347

376-
func cutNode(heap *fibHeap, node *Entry) {
348+
func cutNode(heap *FloatingFibonacciHeap, node *Entry) {
377349
node.marked = false
378350

379351
if node.parent == nil {

fibheap/fibheap_examples_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ func ExampleFloatingFibonacciHeap_Merge() {
9494
fmt.Printf("Minimal element of heap 1: %v\n", min.Priority)
9595
min, _ = heap2.Min()
9696
fmt.Printf("Minimal element of heap 2: %v\n", min.Priority)
97-
heap, _ := heap1.Merge(heap2)
97+
heap, _ := heap1.Merge(&heap2)
9898
min, _ = heap.Min()
9999
fmt.Printf("Minimal element of merged heap: %v\n", min.Priority)
100100
// Output:

fibheap/fibheap_single_example_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ func Example() {
3030
fmt.Printf("Heap 2 is empty? %v\n", heap2.IsEmpty())
3131

3232
fmt.Printf("\nMerge Heap 1 and Heap 2.\n")
33-
mergedHeap, _ := heap1.Merge(heap2)
33+
mergedHeap, _ := heap1.Merge(&heap2)
3434
fmt.Printf("Merged heap size: %v\n", mergedHeap.Size())
3535
fmt.Printf("Set node with priority %v to new priority %v\n", SomeNumberAroundMinus1000, SomeNumberAroundMinus1003)
3636

fibheap/fibheap_test.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -306,7 +306,7 @@ func TestMerge(t *testing.T) {
306306
heap1.Enqueue(NumberSequence4[i])
307307
}
308308

309-
heap, err := heap1.Merge(heap2)
309+
heap, err := heap1.Merge(&heap2)
310310
assert.NoError(t, err)
311311

312312
var min *Entry
@@ -322,7 +322,7 @@ func TestFibHeap_Merge_NilHeap(t *testing.T) {
322322
heap = NewFloatFibHeap()
323323
newHeap, err := heap.Merge(nil)
324324
assert.EqualError(t, err, "One of the heaps to merge is nil. Cannot merge")
325-
assert.Nil(t, newHeap)
325+
assert.Equal(t, newHeap, FloatingFibonacciHeap{})
326326
}
327327

328328
// ***************
@@ -421,7 +421,7 @@ func BenchmarkFibHeap_Merge(b *testing.B) {
421421
for i := 0; i < b.N; i++ {
422422
heap1.Enqueue(2 * 1E10 * (rand.Float64() - 0.5))
423423
heap2.Enqueue(2 * 1E10 * (rand.Float64() - 0.5))
424-
_, err := heap1.Merge(heap2)
424+
_, err := heap1.Merge(&heap2)
425425
assert.NoError(b, err)
426426
}
427427
}

0 commit comments

Comments
 (0)