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.
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module PairingHeap
4
- VERSION = "0.3.0"
4
+ VERSION = "1.0.0"
5
5
  end
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
- stack = []
12
- current = heaps
13
- while current
14
- prev = current
15
- current = current.next_sibling
16
- unless current
17
- stack << prev
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 = current.next_sibling
21
- stack << meld(prev, current)
22
- current = next_val
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
- while true
31
- right = stack.pop
32
- return right if stack.empty?
33
-
34
- left = stack.pop
35
- stack << meld(left, right)
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, subheaps, parent, prev_sibling, next_sibling)
50
+ def initialize(elem, priority)
47
51
  @elem = elem
48
52
  @priority = priority
49
- @subheaps = subheaps
50
- @parent = parent
51
- @prev_sibling = prev_sibling
52
- @next_sibling = 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, nil, nil, nil, nil)
89
+ node = Node.new(elem, priority)
86
90
  @nodes[elem] = node
87
- @root = meld(@root, node)
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 [ArgumEntError] if the heap is empty
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 heap is not in heap or the new priority is less prioritary
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 heap is not in heap
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
- new_heap.prev_sibling = nil
188
- new_heap.next_sibling = nil
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, subheaps, next_sibling)
245
+ def initialize(elem, priority)
223
246
  @elem = elem
224
247
  @priority = priority
225
- @subheaps = subheaps
226
- @next_sibling = 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, nil, nil)
246
- @root = meld(@root, node)
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
- if @root
293
- @root.next_sibling = nil
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 heap is not in the heap
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.3.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-02-08 00:00:00.000000000 Z
11
+ date: 2022-09-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: minitest