Skip to content

Commit dd1dc71

Browse files
Merge pull request #161 from nikox94/FibonacciHeap
Implement Fibonacci heap
2 parents 6e483a4 + 283a4be commit dd1dc71

File tree

13 files changed

+1157
-5
lines changed

13 files changed

+1157
-5
lines changed

README.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,10 @@ and ensure goroutines quit so objects can be GC'd. Threadsafety is achieved
4949
using only CAS operations making this queue quite fast. Benchmarks can be found
5050
in that package.
5151

52+
#### Fibonacci Heap
53+
54+
A standard Fibonacci heap providing the usual operations. Can be useful in executing Dijkstra or Prim's algorithms in the theoretically minimal time. Also useful as a general-purpose priority queue. The special thing about Fibonacci heaps versus other heap variants is the cheap decrease-key operation. This heap has a constant complexity for find minimum, insert and merge of two heaps, an amortized constant complexity for decrease key and O(log(n)) complexity for a deletion or dequeue minimum. In practice the constant factors are large, so Fibonacci heaps could be slower than Pairing heaps, depending on usage. Benchmarks - in the project subfolder. The heap has not been designed for thread-safety.
55+
5256
#### Range Tree
5357

5458
Useful to determine if n-dimensional points fall within an n-dimensional range.
@@ -147,7 +151,7 @@ method which in turn calls into runtime.assertI2T. We need generics.
147151

148152
#### Immutable B Tree
149153
A btree based on two principals, immutablability and concurrency.
150-
Somewhat slow for single value lookups and puts, it is very fast for bulk operations.
154+
Somewhat slow for single value lookups and puts, it is very fast for bulk operations.
151155
A persister can be injected to make this index persistent.
152156

153157
#### Ctrie

datastructures.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import (
1616
_ "github.com/Workiva/go-datastructures/bitarray"
1717
_ "github.com/Workiva/go-datastructures/btree/palm"
1818
_ "github.com/Workiva/go-datastructures/btree/plus"
19+
_ "github.com/Workiva/go-datastructures/fibheap"
1920
_ "github.com/Workiva/go-datastructures/futures"
2021
_ "github.com/Workiva/go-datastructures/hashmap/fastinteger"
2122
_ "github.com/Workiva/go-datastructures/numerics/optimization"

documentation.md

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
The goal of the go-datastructures library is to port implementations of some common datastructures to Go or to improve on some existing datastructures. These datastructures are designed to be re-used for anyone that needs them throughout the community. (and hopefully improved upon).
44

5-
Given the commonality and popularity of these datastructures in other languages, it is hoped that by open sourcing this library we an leverage a great deal of institutional knowledge to improve upon the Go-specific implementations.
5+
Given the commonality and popularity of these datastructures in other languages, it is hoped that by open sourcing this library we leverage a great deal of institutional knowledge to improve upon the Go-specific implementations.
66

77
# Datastructures
88

@@ -16,7 +16,7 @@ The actual implementation is a top-down red-black binary search tree.
1616

1717
### Future
1818

19-
Implement a bottom-up version as well.
19+
Implement a bottom-up version as well.
2020

2121
## Bit Array
2222

@@ -46,7 +46,7 @@ When I get time, I'd like to implement a lockless ring buffer for further perfor
4646

4747
## Range Tree
4848

49-
The range tree is a way to store n-dimensional points of data in a manner that it permits logarithmic queries. These points are usually representing as points on a Cartesian graph represented by integers.
49+
The range tree is a way to store n-dimensional points of data in a manner that permits logarithmic-complexity queries. These points are usually represented as points on a Cartesian graph represented by integers.
5050

5151
There are two implementations of a range tree in this package, one that is mutable and one that is immutable. The mutable version can be faster, but involves lock contention if the consumer needs to ensure threadsafety. The immutable version is a copy-on-write range tree that is optimized by only copying portions of the rangetree on write and is best written to in batches. Operations on the immutable version are slower, but it is safe to read and write from this version at the same time from different threads.
5252

@@ -56,6 +56,14 @@ Although rangetrees are often represented as BBSTs as described above, the n-dim
5656

5757
Unite both implementations of the rangetree under the same interface. The implementations (especially the immutable one) could use some futher performance optimizations.
5858

59+
## Fibonacci Heap
60+
61+
The usual Fibonacci Heap with a floating-point priority key. Does a good job as a priority queue, especially for large n. Should be useful in writing an optimal solution for Dijkstra's and Prim's algorithms. (because of it's efficient decrease-key)
62+
63+
### Future
64+
65+
I'd like to add a value interface{} pointer that will be able to hold any user data attached to each node in the heap. Another thing would be writing a fast implementation of Dijkstra and Prim using this structure. And a third would be analysing thread-safety and coming up with a thread-safe variant.
66+
5967
## Set
6068

6169
Not much to say here. This is an unordered set back by a Go map. This particular version is threadsafe which does hinder performance a bit, although reads can happen simultaneously.
@@ -76,4 +84,4 @@ This package just wraps some common interfaces with a lock to make them threadsa
7684

7785
There is a PR into the datastructures repo that contains some pieces required for implementing a B+ tree. With a B+ tree and bitmap, the pieces are in place to write a native Go database. Going forward, I'd like to take these pieces, expand upon them, and implement a fast database in Go.
7886

79-
As always, any optimizations or bug fixes in any of this code would be greatly appreciated and encouraged :). These datastructures can and are the foundations of many programs and algorithms, even if they are abstracted away in different libraries which makes working with them a lot of fun and very informative.
87+
As always, any optimizations or bug fixes in any of this code would be greatly appreciated and encouraged :). These datastructures can and are the foundations of many programs and algorithms, even if they are abstracted away in different libraries which makes working with them a lot of fun and very informative.
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
l = [-2901939070.965906, 4539462982.372177, -6222008480.049856,
2+
-1400427921.5968666, 9866088144.060883,
3+
-2943107648.529664, 8985474333.11443,
4+
9204710651.257133, 5354113876.8447075,
5+
8122228442.770859, -8121418938.303131,
6+
538431208.3261185, 9913821013.519611,
7+
-8722989752.449871, -3091279426.694975,
8+
7229910558.195713, -2908838839.99403,
9+
2835257231.305996, 3922059795.3656673,
10+
-9298869735.322557]
11+
12+
print(l)
13+
14+
l = sorted(l)
15+
print(l)
16+
a1 = l[19]
17+
a2 = -8722989752.449871
18+
print(str(a1) + " -> " + str(a2))
19+
l[19] = a2
20+
21+
b1 = l[18]
22+
b2 = -9698869735.322557
23+
print(str(b1) + " -> " + str(b2))
24+
l[18] = b2
25+
26+
c1 = l[17]
27+
c2 = -9804710651.257133
28+
print(str(c1) + " -> " + str(c2))
29+
l[17] = c2
30+
31+
print(sorted(l))
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
l = [-2901939070.965906, 4539462982.372177, -6222008480.049856,
2+
-1400427921.5968666, 9866088144.060883, -2943107648.529664, 8985474333.11443,
3+
9204710651.257133, 5354113876.8447075, 8122228442.770859, -8121418938.303131,
4+
538431208.3261185, 9913821013.519611, -8722989752.449871, -3091279426.694975,
5+
7229910558.195713, -2908838839.99403, 2835257231.305996, 3922059795.3656673,
6+
-9298869735.322557]
7+
8+
print(l)
9+
10+
l = sorted(l)
11+
print(l)
12+
a1 = l[19]
13+
a2 = 0
14+
print(str(a1) + " -> " + str(a2))
15+
l[19] = a2
16+
17+
b1 = l[18]
18+
b2 = 0
19+
print(str(b1) + " -> " + str(b2))
20+
l[18] = b2
21+
22+
c1 = l[17]
23+
c2 = 0
24+
print(str(c1) + " -> " + str(c2))
25+
l[17] = c2
26+
27+
print(sorted(l))
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
#!/usr/bin/python3
2+
3+
import random
4+
5+
l = []
6+
for i in range(20):
7+
l.append(random.uniform(-1E10, 1E10))
8+
9+
print(l)
10+
l = sorted(l)
11+
print(l)

fibheap/Test Generator/Merge.py

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
import random
2+
3+
l1 = []
4+
l2 = []
5+
for i in range(20):
6+
l1.append(random.uniform(-1E10, 1E10))
7+
l2.append(random.uniform(-1E10, 1E10))
8+
9+
10+
print(l1)
11+
print(l2)
12+
13+
l = []
14+
l.extend(l1)
15+
l.extend(l2)
16+
17+
print(sorted(l))
18+
19+
'''
20+
[6015943293.071386, -3878285748.0708866, 8674121166.062424, -1528465047.6118088,
21+
7584260716.494843, -373958476.80486107, -6367787695.054295, 6813992306.719868,
22+
5986097626.907181, 9011134545.052086, 7123644338.268343, 2646164210.08445,
23+
4407427446.995375, -888196668.2563229, 7973918726.985172, -6529216482.09644,
24+
6079069259.51853, -8415952427.784341, -6859960084.757652, -502409126.89040375]
25+
[9241165993.258648, -9423768405.578083, 3280085607.6687145, -5253703037.682413,
26+
3858507441.2785892, 9896256282.896187, -9439606732.236805, 3082628799.5320206,
27+
9453124863.59945, 9928066165.458393, 1135071669.4712334, 6380353457.986282,
28+
8329064041.853199, 2382910730.445751, -8478491750.445316, 9607469190.690144,
29+
5417691217.440792, -9698248424.421888, -3933774735.280322, -5984555343.381466]
30+
[-9698248424.421888, -9439606732.236805, -9423768405.578083, -8478491750.445316,
31+
-8415952427.784341, -6859960084.757652, -6529216482.09644, -6367787695.054295,
32+
-5984555343.381466, -5253703037.682413, -3933774735.280322, -3878285748.0708866,
33+
-1528465047.6118088, -888196668.2563229, -502409126.89040375,
34+
-373958476.80486107, 1135071669.4712334, 2382910730.445751, 2646164210.08445,
35+
3082628799.5320206, 3280085607.6687145, 3858507441.2785892, 4407427446.995375,
36+
5417691217.440792, 5986097626.907181, 6015943293.071386, 6079069259.51853,
37+
6380353457.986282, 6813992306.719868, 7123644338.268343, 7584260716.494843,
38+
7973918726.985172, 8329064041.853199, 8674121166.062424, 9011134545.052086,
39+
9241165993.258648, 9453124863.59945, 9607469190.690144, 9896256282.896187,
40+
9928066165.458393]
41+
'''

fibheap/Test Generator/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
These are some Python helper scripts to help generate sample test arrays.

fibheap/benchmarks.txt

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
BenchmarkFibHeap_Enqueue-4 10000000 280 ns/op 64 B/op 1 allocs/op
2+
BenchmarkFibHeap_DequeueMin-4 100 16990302 ns/op 16007168 B/op 2 allocs/op
3+
BenchmarkFibHeap_DecreaseKey-4 20000000 900 ns/op 122 B/op 3 allocs/op
4+
BenchmarkFibHeap_Delete-4 100 19087592 ns/op 16007168 B/op 2 allocs/op
5+
BenchmarkFibHeap_Merge-4 3000000 482 ns/op 128 B/op 2 allocs/op
6+
PASS
7+
coverage: 96.2% of statements
8+
ok _/home/nikola/git/go-datastructures/fibheap 37.206s

0 commit comments

Comments
 (0)