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.
@@ -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