pairing_heap 0.3.0 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|