pairing_heap 0.3.0 → 1.0.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 +4 -4
- data/.github/workflows/main.yml +11 -8
- data/README.md +324 -289
- data/lib/pairing_heap/version.rb +1 -1
- data/lib/pairing_heap.rb +82 -50
- metadata +2 -2
data/lib/pairing_heap/version.rb
CHANGED
data/lib/pairing_heap.rb
CHANGED
@@ -8,18 +8,21 @@ module PairingHeap
|
|
8
8
|
return heaps if heaps.next_sibling.nil?
|
9
9
|
|
10
10
|
# [H1, H2, H3, H4, H5, H6, H7] => [H1H2, H3H4, H5H6, H7]
|
11
|
-
|
12
|
-
|
13
|
-
while
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
11
|
+
pairs = nil
|
12
|
+
left = heaps
|
13
|
+
while left
|
14
|
+
right = left.next_sibling
|
15
|
+
unless right
|
16
|
+
left.next_sibling = pairs
|
17
|
+
pairs = left
|
18
18
|
break
|
19
19
|
end
|
20
|
-
next_val =
|
21
|
-
|
22
|
-
|
20
|
+
next_val = right.next_sibling
|
21
|
+
right = meld(left, right)
|
22
|
+
right.next_sibling = pairs
|
23
|
+
pairs = right
|
24
|
+
|
25
|
+
left = next_val
|
23
26
|
end
|
24
27
|
|
25
28
|
# [H1H2, H3H4, H5H6, H7]
|
@@ -27,13 +30,14 @@ module PairingHeap
|
|
27
30
|
# [H1H2, H3H45H67]
|
28
31
|
# [H1H2H3H45H67]
|
29
32
|
# return H1H2H3H45H67
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
left =
|
35
|
-
|
33
|
+
left = pairs
|
34
|
+
right = pairs.next_sibling
|
35
|
+
while right
|
36
|
+
next_val = right.next_sibling
|
37
|
+
left = meld(left, right)
|
38
|
+
right = next_val
|
36
39
|
end
|
40
|
+
left
|
37
41
|
end
|
38
42
|
end
|
39
43
|
private_constant :MergePairs
|
@@ -43,13 +47,13 @@ module PairingHeap
|
|
43
47
|
class PairingHeap
|
44
48
|
class Node
|
45
49
|
attr_accessor :elem, :priority, :subheaps, :parent, :prev_sibling, :next_sibling
|
46
|
-
def initialize(elem, priority
|
50
|
+
def initialize(elem, priority)
|
47
51
|
@elem = elem
|
48
52
|
@priority = priority
|
49
|
-
@subheaps =
|
50
|
-
@parent =
|
51
|
-
@prev_sibling =
|
52
|
-
@next_sibling =
|
53
|
+
@subheaps = nil
|
54
|
+
@parent = nil
|
55
|
+
@prev_sibling = nil
|
56
|
+
@next_sibling = nil
|
53
57
|
end
|
54
58
|
|
55
59
|
def remove_from_parents_list!
|
@@ -82,12 +86,17 @@ module PairingHeap
|
|
82
86
|
def push(elem, priority)
|
83
87
|
raise ArgumentError, "Element already in the heap" if @nodes.key?(elem)
|
84
88
|
|
85
|
-
node = Node.new(elem, priority
|
89
|
+
node = Node.new(elem, priority)
|
86
90
|
@nodes[elem] = node
|
87
|
-
|
91
|
+
if @root
|
92
|
+
@root = meld(@root, node)
|
93
|
+
else
|
94
|
+
@root = node
|
95
|
+
end
|
88
96
|
self
|
89
97
|
end
|
90
98
|
alias enqueue push
|
99
|
+
alias offer push
|
91
100
|
|
92
101
|
# Returns the element at the top of the heap
|
93
102
|
# Time Complexity: O(1)
|
@@ -96,6 +105,10 @@ module PairingHeap
|
|
96
105
|
end
|
97
106
|
|
98
107
|
def peek_priority
|
108
|
+
@root&.priority
|
109
|
+
end
|
110
|
+
|
111
|
+
def peek_with_priority
|
99
112
|
[@root&.elem, @root&.priority]
|
100
113
|
end
|
101
114
|
|
@@ -118,11 +131,10 @@ module PairingHeap
|
|
118
131
|
end
|
119
132
|
alias length size
|
120
133
|
|
121
|
-
# Removes element from the top of the heap
|
134
|
+
# Removes element from the top of the heap and returns it
|
122
135
|
# Time Complexity: O(N)
|
123
136
|
# Amortized time Complexity: O(log(N))
|
124
|
-
# @raise [
|
125
|
-
# @return [PairingHeap]
|
137
|
+
# @raise [ArgumentError] if the heap is empty
|
126
138
|
def pop
|
127
139
|
raise ArgumentError, "Cannot remove from an empty heap" if @root.nil?
|
128
140
|
|
@@ -149,7 +161,7 @@ module PairingHeap
|
|
149
161
|
# Amortized Time Complexity: o(log(N))
|
150
162
|
# @param elem Element
|
151
163
|
# @param priority New priority
|
152
|
-
# @raise [ArgumentError] if the element
|
164
|
+
# @raise [ArgumentError] if the element is not in the heap or the new priority is less prioritary
|
153
165
|
# @return [PairingHeap]
|
154
166
|
def change_priority(elem, priority)
|
155
167
|
node = @nodes[elem]
|
@@ -171,7 +183,7 @@ module PairingHeap
|
|
171
183
|
# Removes element from the heap
|
172
184
|
# Time Complexity: O(N)
|
173
185
|
# Amortized Time Complexity: O(log(N))
|
174
|
-
# @raise [ArgumentError] if the element
|
186
|
+
# @raise [ArgumentError] if the element is not in the heap
|
175
187
|
# @return [PairingHeap]
|
176
188
|
def delete(elem)
|
177
189
|
node = @nodes[elem]
|
@@ -180,26 +192,37 @@ module PairingHeap
|
|
180
192
|
@nodes.delete(elem)
|
181
193
|
if node.parent.nil?
|
182
194
|
@root = merge_pairs(node.subheaps)
|
195
|
+
if @root
|
196
|
+
@root.parent = nil
|
197
|
+
@root.prev_sibling = nil
|
198
|
+
@root.next_sibling = nil
|
199
|
+
end
|
183
200
|
else
|
184
201
|
node.remove_from_parents_list!
|
185
202
|
new_heap = merge_pairs(node.subheaps)
|
186
203
|
if new_heap
|
187
|
-
|
188
|
-
|
204
|
+
@root = meld(new_heap, @root)
|
205
|
+
@root.parent = nil
|
206
|
+
@root.prev_sibling = nil
|
207
|
+
@root.next_sibling = nil
|
189
208
|
end
|
190
|
-
@root = meld(new_heap, @root)
|
191
209
|
end
|
192
|
-
@root&.parent = nil
|
193
210
|
self
|
194
211
|
end
|
195
212
|
|
213
|
+
# Returns priority of the provided element
|
214
|
+
# Time Complexity: O(1)
|
215
|
+
# @raise [ArgumentError] if the element is not in the heap
|
216
|
+
def get_priority(elem)
|
217
|
+
node = @nodes[elem]
|
218
|
+
raise ArgumentError, "Provided element is not in heap" if node.nil?
|
219
|
+
node.priority
|
220
|
+
end
|
221
|
+
|
196
222
|
private
|
197
223
|
include MergePairs
|
198
224
|
|
199
225
|
def meld(left, right)
|
200
|
-
return right if left.nil?
|
201
|
-
return left if right.nil?
|
202
|
-
|
203
226
|
if @order[left.priority, right.priority]
|
204
227
|
parent = left
|
205
228
|
child = right
|
@@ -219,11 +242,11 @@ module PairingHeap
|
|
219
242
|
class SimplePairingHeap
|
220
243
|
class Node
|
221
244
|
attr_accessor :elem, :priority, :subheaps, :next_sibling
|
222
|
-
def initialize(elem, priority
|
245
|
+
def initialize(elem, priority)
|
223
246
|
@elem = elem
|
224
247
|
@priority = priority
|
225
|
-
@subheaps =
|
226
|
-
@next_sibling =
|
248
|
+
@subheaps = nil
|
249
|
+
@next_sibling = nil
|
227
250
|
end
|
228
251
|
end
|
229
252
|
private_constant :Node
|
@@ -239,15 +262,19 @@ module PairingHeap
|
|
239
262
|
# Time Complexity: O(1)
|
240
263
|
# @param elem Element to be pushed
|
241
264
|
# @param priority Priority of the element
|
242
|
-
# @raise [ArgumentError] if the element is already in the heap
|
243
265
|
# @return [PairingHeap]
|
244
266
|
def push(elem, priority)
|
245
|
-
node = Node.new(elem, priority
|
246
|
-
|
267
|
+
node = Node.new(elem, priority)
|
268
|
+
if @root
|
269
|
+
@root = meld(@root, node)
|
270
|
+
else
|
271
|
+
@root = node
|
272
|
+
end
|
247
273
|
@size += 1
|
248
274
|
self
|
249
275
|
end
|
250
276
|
alias enqueue push
|
277
|
+
alias offer push
|
251
278
|
|
252
279
|
# Returns the element at the top of the heap
|
253
280
|
# Time Complexity: O(1)
|
@@ -256,6 +283,10 @@ module PairingHeap
|
|
256
283
|
end
|
257
284
|
|
258
285
|
def peek_priority
|
286
|
+
@root&.priority
|
287
|
+
end
|
288
|
+
|
289
|
+
def peek_with_priority
|
259
290
|
[@root&.elem, @root&.priority]
|
260
291
|
end
|
261
292
|
|
@@ -278,25 +309,29 @@ module PairingHeap
|
|
278
309
|
end
|
279
310
|
alias length size
|
280
311
|
|
281
|
-
# Removes element from the top of the heap
|
312
|
+
# Removes element from the top of the heap and returns it
|
282
313
|
# Time Complexity: O(N)
|
283
314
|
# Amortized time Complexity: O(log(N))
|
284
315
|
# @raise [ArgumEntError] if the heap is empty
|
285
|
-
# @return [PairingHeap]
|
286
316
|
def pop
|
287
317
|
raise ArgumentError, "Cannot remove from an empty heap" if @root.nil?
|
288
318
|
@size -= 1
|
289
319
|
|
290
320
|
elem = @root.elem
|
291
321
|
@root = merge_pairs(@root.subheaps)
|
292
|
-
|
293
|
-
|
294
|
-
end
|
322
|
+
@root&.next_sibling = nil
|
323
|
+
|
295
324
|
elem
|
296
325
|
end
|
297
326
|
alias dequeue pop
|
298
327
|
|
299
328
|
def pop_priority
|
329
|
+
node = @root
|
330
|
+
pop
|
331
|
+
node.priority
|
332
|
+
end
|
333
|
+
|
334
|
+
def pop_with_priority
|
300
335
|
node = @root
|
301
336
|
pop
|
302
337
|
[node.elem, node.priority]
|
@@ -306,9 +341,6 @@ module PairingHeap
|
|
306
341
|
include MergePairs
|
307
342
|
|
308
343
|
def meld(left, right)
|
309
|
-
return right if left.nil?
|
310
|
-
return left if right.nil?
|
311
|
-
|
312
344
|
if @order[left.priority, right.priority]
|
313
345
|
parent = left
|
314
346
|
child = right
|
@@ -350,7 +382,7 @@ module PairingHeap
|
|
350
382
|
# Changes a priority of the element to a more prioritary one
|
351
383
|
# Time Complexity: O(N)
|
352
384
|
# Amortized Time Complexity: O(log(N))
|
353
|
-
# @raise [ArgumentError] if the element
|
385
|
+
# @raise [ArgumentError] if the element is not in the heap
|
354
386
|
# @return [PairingHeap]
|
355
387
|
def change_priority(elem, priority)
|
356
388
|
raise ArgumentError, "Provided element is not in heap" unless @nodes.key?(elem)
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: pairing_heap
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 1.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Marcin Henryk Bartkowiak
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-
|
11
|
+
date: 2022-09-04 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: minitest
|