fibonacci_heap 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 9d5517c8d52edce5c8e372cd14457efe425f6a422fec8a02585221df8fa2f25a
4
- data.tar.gz: 3a6e50318184cfa233fe840e91806a209379dccc5dde84f7739b8921e3d73712
3
+ metadata.gz: 68aaf5872d76003db0e72b8e732fb657cf02da219739fb152739bc943cd19ef5
4
+ data.tar.gz: 9ac530f4499a41aca100ad0b7f22f802f161f8b5c51b0f5137cc181301a9b19a
5
5
  SHA512:
6
- metadata.gz: 6a93299721795318e9cd8529e899d710a32fb2bfde25b825d31a37a1318e78afa62bece5d26d4010a3a1cfa8c6a6420c5754c47e14cc56f02f1a40545911c37a
7
- data.tar.gz: 4790e9bbf353167b8a018e9e2a6b463a4159b5e5b0d434895e850466c495f55df7e92fc4744c2c25120c6474d4219382b428f905f82e56051d053db59710bd74
6
+ metadata.gz: 1bd78f32dabd4ac5763f2c6452c4be430e077cbf0f10290a7792cf97599439d7eeb369c6aed42cc3e473657025583b4eb98f868ad45cc6a76aa444a2f6228d32
7
+ data.tar.gz: 0532212274f8f18902664c608b0bf3fe2a933eec70e84249b5f0f891795ccafb3dcb0ccdccdbd75dba6e412cc1146d82476999a09b9bf32d7d22f5dbecb70d5e
data/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  A Ruby implementation of the [Fibonacci heap](https://en.wikipedia.org/wiki/Fibonacci_heap) data structure ideal for use as a priority queue with [Dijkstra's algorithm](https://en.wikipedia.org/wiki/Dijkstra's_algorithm#Using_a_priority_queue).
4
4
 
5
- **Current version:** 0.1.0
5
+ **Current version:** 0.2.0
6
6
  **Supported Ruby versions:** 1.8.7, 1.9.2, 1.9.3, 2.0, 2.1, 2.2, 2.3
7
7
 
8
8
  ## Installation
@@ -45,6 +45,7 @@ heap.pop
45
45
  * [`#pop`](#fibonacciheapheappop)
46
46
  * [`#decrease_key(x, k)`](#fibonacciheapheapdecrease_keyx-k)
47
47
  * [`#delete(x)`](#fibonacciheapheapdeletex)
48
+ * [`#clear`](#fibonacciheapheapclear)
48
49
  * [`FibonacciHeap::Node`](#fibonacciheapnode)
49
50
  * [`new(key[, value])`](#fibonacciheapnodenewkey-value)
50
51
  * [`key`](#fibonacciheapnodekey)
@@ -66,7 +67,7 @@ heap = FibonacciHeap::Heap.new
66
67
  #=> #<FibonacciHeap n=0 min=nil>
67
68
  ```
68
69
 
69
- Return a new, empty `FibonacciHeap::Heap` instance.
70
+ Return a new, empty [`FibonacciHeap::Heap`](#fibonacciheapheap) instance.
70
71
 
71
72
  #### `FibonacciHeap::Heap#n`
72
73
 
@@ -105,7 +106,7 @@ heap.min
105
106
  #=> #<FibonacciHeap::Node key=1 ...>
106
107
  ```
107
108
 
108
- Return the smallest `FibonacciHeap::Node` node in the heap as determined by the node's `key`.
109
+ Return the smallest [`FibonacciHeap::Node`](#fibonacciheapnode) node in the heap as determined by the node's `key`.
109
110
 
110
111
  Will return `nil` if the heap is empty.
111
112
 
@@ -119,7 +120,7 @@ heap.insert(node)
119
120
  heap.insert(bar, 100)
120
121
  ```
121
122
 
122
- Insert the given `FibonacciHeap::Node` `x` into the heap with an optional key `k`.
123
+ Insert the given [`FibonacciHeap::Node`](#fibonacciheapnode) `x` into the heap with an optional key `k`.
123
124
 
124
125
  Defaults to using `x`'s existing `key` for `k`.
125
126
 
@@ -140,7 +141,7 @@ heap3.pop
140
141
  #=> #<FibonacciHeap::Node key=2 value="bar" ...>
141
142
  ```
142
143
 
143
- Unite the given `FibonacciHeap::Heap` `h2` with this one in a new `FibonacciHeap::Heap`.
144
+ Unite the given [`FibonacciHeap::Heap`](#fibonacciheapheap) `h2` with this one in a new [`FibonacciHeap::Heap`](#fibonacciheapheap).
144
145
 
145
146
  As this will mutate both collections of rooted trees, attempting to use either the original heap or `h2` after `concat` has undefined behaviour.
146
147
 
@@ -153,7 +154,7 @@ heap.pop
153
154
  #=> #<FibonacciHeap::Node key=1 value="foo" ...>
154
155
  ```
155
156
 
156
- Remove and return the smallest `FibonacciHeap::Node` from the heap.
157
+ Remove and return the smallest [`FibonacciHeap::Node`](#fibonacciheapnode) from the heap.
157
158
 
158
159
  #### `FibonacciHeap::Heap#decrease_key(x, k)`
159
160
 
@@ -165,11 +166,11 @@ heap.decrease_key(node, 0)
165
166
  #=> #<FibonacciHeap::Node key=0 value="foo">
166
167
  ```
167
168
 
168
- Decrease the key of the given `FibonacciHeap::Node` `x` to the new given key `k`.
169
+ Decrease the key of the given [`FibonacciHeap::Node`](#fibonacciheapnode) `x` to the new given key `k`.
169
170
 
170
171
  The node must already be inserted into the heap and the key must be comparable.
171
172
 
172
- Raises a `FibonacciHeap::InvalidKeyError` if the new key is greater than the current key.
173
+ Raises a [`FibonacciHeap::InvalidKeyError`](#fibonacciheapinvalidkeyerror) if the new key is greater than the current key.
173
174
 
174
175
  #### `FibonacciHeap::Heap#delete(x)`
175
176
 
@@ -181,13 +182,24 @@ heap.delete(node)
181
182
  #=> #<FibonacciHeap::Node key=-Infinity value="foo">
182
183
  ```
183
184
 
184
- Deletes the given `FibonacciHeap::Node` `x` from the heap.
185
+ Deletes the given [`FibonacciHeap::Node`](#fibonacciheapnode) `x` from the heap.
185
186
 
186
187
  The node must already be inserted into the heap.
187
188
 
189
+ #### `FibonacciHeap::Heap#clear`
190
+
191
+ ```ruby
192
+ heap = FibonacciHeap::Heap.new
193
+ heap.insert(FibonacciHeap::Node.new(1, 'foo'))
194
+ heap.clear
195
+ #=> #<FibonacciHeap::Heap n=0 min=nil>
196
+ ```
197
+
198
+ Remove all nodes from the heap, emptying it.
199
+
188
200
  ### `FibonacciHeap::Node`
189
201
 
190
- A single node in a `FibonacciHeap::Heap`.
202
+ A single node in a [`FibonacciHeap::Heap`](#fibonacciheapheap).
191
203
 
192
204
  Used internally to form both min-heap ordered trees and circular, doubly linked lists.
193
205
 
@@ -200,7 +212,7 @@ node = FibonacciHeap::Node.new(1, 'foo')
200
212
  #=> #<FibonacciHeap::Node key=1 value="foo">
201
213
  ```
202
214
 
203
- Return a new `FibonacciHeap::Node` with the given key `key` and an optional value `value`.
215
+ Return a new [`FibonacciHeap::Node`](#fibonacciheapnode) with the given key `key` and an optional value `value`.
204
216
 
205
217
  Defaults to using the `key` as the value.
206
218
 
@@ -226,7 +238,7 @@ Return the current value of the node.
226
238
 
227
239
  ### `FibonacciHeap::InvalidKeyError`
228
240
 
229
- Raised when attempting to decrease a key but the key is greater than the current key.
241
+ Raised when attempting to decrease a key but the new key is greater than the current key.
230
242
 
231
243
  ## References
232
244
 
@@ -66,7 +66,7 @@ module FibonacciHeap
66
66
  list.sentinel.prev.next = sentinel.next
67
67
  sentinel.next.prev = list.sentinel.prev
68
68
  sentinel.next = list.sentinel.next
69
- list.sentinel.prev = sentinel
69
+ list.sentinel.next.prev = sentinel
70
70
  end
71
71
 
72
72
  # Yield each element of this list.
@@ -26,6 +26,7 @@ module FibonacciHeap
26
26
  @min = nil
27
27
  end
28
28
 
29
+ # Return whether or not this heap is empty.
29
30
  def empty?
30
31
  n.zero?
31
32
  end
@@ -65,15 +66,16 @@ module FibonacciHeap
65
66
  # Unite the given Fibonacci heap into this one, returning a new heap.
66
67
  #
67
68
  # Note that uniting the heaps will mutate their root lists, destroying them
68
- # both so attempting to use them has undefined behaviour.
69
+ # both so attempting to use them after uniting has undefined behaviour.
69
70
  #
70
71
  # Corresponds to the Fib-Heap-Union(H1, H2) procedure.
71
72
  def concat(h2)
72
73
  h = self.class.new
73
74
  h.min = min
74
75
 
75
- h.root_list = root_list
76
- h.root_list.concat(h2.root_list)
76
+ h.root_list = CircularDoublyLinkedList.new
77
+ h.root_list.concat(root_list) unless empty?
78
+ h.root_list.concat(h2.root_list) unless h2.empty?
77
79
 
78
80
  h.min = h2.min if !min || (h2.min && h2.min.key < min.key)
79
81
 
@@ -90,34 +92,30 @@ module FibonacciHeap
90
92
  # Corresponds to the Fib-Heap-Extract-Min(H) procedure.
91
93
  def pop
92
94
  z = min
95
+ return unless z
93
96
 
94
- if z
95
- # For each child x of z
96
- z.child_list.each do |x|
97
-
98
- # Add x to the root list of H
99
- root_list.insert(x)
100
- x.p = nil
101
- end
102
-
103
- # Remove z from the root list of H
104
- root_list.delete(z)
97
+ # For each child x of z
98
+ z.child_list.each do |x|
99
+ # Add x to the root list of H
100
+ root_list.insert(x)
101
+ x.p = nil
102
+ end
105
103
 
106
- # Is z the only node on the root list?
107
- if z.right == z.left
108
- # Empty the heap
109
- self.min = nil
110
- self.root_list = CircularDoublyLinkedList.new
111
- else
112
- # Set min to another root
113
- self.min = root_list.head
104
+ # Remove z from the root list of H
105
+ root_list.delete(z)
114
106
 
115
- consolidate
116
- end
107
+ # Was z the only node on the root list?
108
+ if z.right == z.left
109
+ self.min = nil
110
+ else
111
+ # Set min to another root
112
+ self.min = root_list.head
117
113
 
118
- self.n -= 1
114
+ consolidate
119
115
  end
120
116
 
117
+ self.n -= 1
118
+
121
119
  z
122
120
  end
123
121
 
@@ -156,6 +154,15 @@ module FibonacciHeap
156
154
  pop
157
155
  end
158
156
 
157
+ # Remove all nodes from the heap, emptying it.
158
+ def clear
159
+ self.root_list = CircularDoublyLinkedList.new
160
+ self.min = nil
161
+ self.n = 0
162
+
163
+ self
164
+ end
165
+
159
166
  def inspect
160
167
  %(#<#{self.class} n=#{n} min=#{min.inspect}>)
161
168
  end
@@ -164,7 +171,9 @@ module FibonacciHeap
164
171
 
165
172
  # Corresponds to the Consolidate(H) procedure.
166
173
  def consolidate
167
- degrees = []
174
+ # let A[0..D(H.n)] be a new array
175
+ max_degree = (Math.log(n) / Math.log(2)).floor
176
+ degrees = Array.new(max_degree + 1)
168
177
 
169
178
  root_list.each do |w|
170
179
  x = w
@@ -186,8 +195,8 @@ module FibonacciHeap
186
195
  end
187
196
 
188
197
  # Empty the root list
189
- self.min = nil
190
198
  self.root_list = CircularDoublyLinkedList.new
199
+ self.min = nil
191
200
 
192
201
  # Reconstruct the root list from the array A
193
202
  degrees.each do |root|
@@ -207,6 +216,7 @@ module FibonacciHeap
207
216
  def link(y, x)
208
217
  # remove y from the root list of H
209
218
  root_list.delete(y)
219
+
210
220
  # make y a child of x, incrementing x.degree
211
221
  x.child_list.insert(y)
212
222
  x.degree += 1
@@ -1,5 +1,3 @@
1
- require 'fibonacci_heap/circular_doubly_linked_list'
2
-
3
1
  module FibonacciHeap
4
2
  # A single node in a Fibonacci Heap.
5
3
  #
@@ -239,7 +239,7 @@ module FibonacciHeap
239
239
  expect(list).to contain_exactly(node, node2, node3, node4)
240
240
  end
241
241
 
242
- it 'combines an empty list a non-empty one' do
242
+ it 'combines an empty list with a non-empty one' do
243
243
  list = described_class.new
244
244
  list2 = described_class.new
245
245
  node = Node.new('foo')
@@ -252,6 +252,18 @@ module FibonacciHeap
252
252
  expect(list).to contain_exactly(node, node2)
253
253
  end
254
254
 
255
+ it 'removes any reference to the other list sentinel' do
256
+ list = described_class.new
257
+ list2 = described_class.new
258
+ node = Node.new('foo')
259
+ list2.insert(node)
260
+
261
+ list.concat(list2)
262
+
263
+ expect(node.next).to eq(list.sentinel)
264
+ expect(node.prev).to eq(list.sentinel)
265
+ end
266
+
255
267
  it 'combines a non-empty list with an empty one' do
256
268
  list = described_class.new
257
269
  list2 = described_class.new
@@ -23,6 +23,42 @@ module FibonacciHeap
23
23
  end
24
24
  end
25
25
 
26
+ describe '#clear' do
27
+ it 'empties the heap' do
28
+ heap = described_class.new
29
+ heap.insert(Node.new(1, 'foo'))
30
+
31
+ heap.clear
32
+
33
+ expect(heap).to be_empty
34
+ end
35
+
36
+ it 'clears the min node' do
37
+ heap = described_class.new
38
+ heap.insert(Node.new(1, 'foo'))
39
+
40
+ heap.clear
41
+
42
+ expect(heap.min).to be_nil
43
+ end
44
+
45
+ it 'empties the root list' do
46
+ heap = described_class.new
47
+ heap.insert(Node.new(1, 'foo'))
48
+
49
+ heap.clear
50
+
51
+ expect(heap.root_list).to be_empty
52
+ end
53
+
54
+ it 'returns the emptied heap' do
55
+ heap = described_class.new
56
+ heap.insert(Node.new(1, 'foo'))
57
+
58
+ expect(heap.clear).to eq(heap)
59
+ end
60
+ end
61
+
26
62
  describe '#n' do
27
63
  it 'returns the size of the heap' do
28
64
  heap = described_class.new
@@ -224,6 +260,28 @@ module FibonacciHeap
224
260
  expect(root.left).not_to eq(root.right)
225
261
  expect(root2.left).not_to eq(root2.right)
226
262
  end
263
+
264
+ it 'removes the last node in the heap' do
265
+ heap = described_class.new
266
+ root = Node.new('foo')
267
+ heap.insert(root)
268
+
269
+ expect(heap.pop).to eq(root)
270
+ expect(heap.pop).to be_nil
271
+ expect(heap.min).to be_nil
272
+ end
273
+
274
+ it 'can have nodes inserted after being emptied' do
275
+ heap = described_class.new
276
+ root = Node.new('foo')
277
+ heap.insert(root)
278
+ heap.pop
279
+ root2 = Node.new('bar')
280
+ heap.insert(root2)
281
+
282
+ expect(heap.pop).to eq(root2)
283
+ expect(heap.pop).to be_nil
284
+ end
227
285
  end
228
286
 
229
287
  describe '#decrease_key' do
@@ -292,7 +350,7 @@ module FibonacciHeap
292
350
  end
293
351
 
294
352
  describe '#concat' do
295
- it 'unite the given heap with this one' do
353
+ it 'unites the given heap with this one' do
296
354
  heap = described_class.new
297
355
  node = Node.new(1)
298
356
  heap2 = described_class.new
@@ -306,6 +364,39 @@ module FibonacciHeap
306
364
  expect(heap3.pop).to eq(node2)
307
365
  expect(heap3.pop).to be_nil
308
366
  end
367
+
368
+ it 'unites an empty heap with a non-empty heap' do
369
+ heap = described_class.new
370
+ heap2 = described_class.new
371
+ node = Node.new(1)
372
+ heap2.insert(node)
373
+
374
+ heap3 = heap.concat(heap2)
375
+
376
+ expect(heap3.pop).to eq(node)
377
+ expect(heap3.pop).to be_nil
378
+ end
379
+
380
+ it 'unites a non-empty heap with an empty heap' do
381
+ heap = described_class.new
382
+ heap2 = described_class.new
383
+ node = Node.new(1)
384
+ heap.insert(node)
385
+
386
+ heap3 = heap.concat(heap2)
387
+
388
+ expect(heap3.pop).to eq(node)
389
+ expect(heap3.pop).to be_nil
390
+ end
391
+
392
+ it 'unites two empty heaps' do
393
+ heap = described_class.new
394
+ heap2 = described_class.new
395
+
396
+ heap3 = heap.concat(heap2)
397
+
398
+ expect(heap3.pop).to be_nil
399
+ end
309
400
  end
310
401
  end
311
402
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fibonacci_heap
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Paul Mucur
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-07-13 00:00:00.000000000 Z
11
+ date: 2018-07-14 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rspec