rbtree-ruby 0.2.1 → 0.2.3

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.
data/lib/rbtree.rb CHANGED
@@ -72,11 +72,15 @@ class RBTree
72
72
 
73
73
  # Initializes a new RBTree.
74
74
  #
75
- # The tree can be initialized empty or populated with initial data from a Hash or Array.
75
+ # The tree can be initialized empty or populated with initial data from a Hash, Array, or Enumerator.
76
+ # A block can also be provided to supply the initial data.
76
77
  #
77
78
  # @param args [Hash, Array, nil] optional initial data
79
+ # @param overwrite [Boolean] whether to overwrite existing keys (default: true)
80
+ # @yieldreturn [Object] optional initial data
78
81
  # - If a Hash is provided, each key-value pair is inserted into the tree
79
82
  # - If an Array is provided, it should contain [key, value] pairs
83
+ # - If a block is provided, it is yielded to get the source data
80
84
  # - If no arguments are provided, an empty tree is created
81
85
  # @raise [ArgumentError] if arguments are invalid
82
86
  # @example Create an empty tree
@@ -85,7 +89,9 @@ class RBTree
85
89
  # tree = RBTree.new({1 => 'one', 2 => 'two'})
86
90
  # @example Create from an array
87
91
  # tree = RBTree.new([[1, 'one'], [2, 'two']])
88
- def initialize(*args)
92
+ # @example Create with overwrite: false
93
+ # tree = RBTree.new([[1, 'one'], [1, 'uno']], overwrite: false)
94
+ def initialize(*args, overwrite: true, &block)
89
95
  @nil_node = Node.new
90
96
  @nil_node.color = Node::BLACK
91
97
  @nil_node.left = @nil_node
@@ -96,34 +102,8 @@ class RBTree
96
102
  @node_pool = [] # Memory pool for recycling nodes
97
103
  @size = 0
98
104
 
99
- if args.any?
100
- source = args.size == 1 ? args.first : args
101
- case source
102
- when Hash
103
- source.each { |k, v| insert(k, v) }
104
- when Array
105
- source.each do |arg|
106
- key, value = arg
107
- insert(key, value)
108
- end
109
- else
110
- raise ArgumentError, "Invalid arguments"
111
- end
112
- end
113
- end
114
-
115
- # Returns a string representation of the tree.
116
- #
117
- # Shows the first 5 entries and total size. Useful for debugging.
118
- #
119
- # @return [String] a human-readable representation of the tree
120
- def inspect
121
- if @size > 0
122
- content = first(5).map { |k, v| "#{k.inspect}=>#{v.inspect}" }.join(", ")
123
- suffix = @size > 5 ? ", ..." : ""
124
- "#<#{self.class}:0x#{object_id.to_s(16)} size=#{@size} {#{content}#{suffix}}>"
125
- else
126
- super
105
+ if args.size > 0 || block_given?
106
+ insert(*args, overwrite: overwrite, &block)
127
107
  end
128
108
  end
129
109
 
@@ -132,6 +112,22 @@ class RBTree
132
112
  # @return [Boolean] true if the tree contains no elements, false otherwise
133
113
  def empty? = @root == @nil_node
134
114
 
115
+ # Returns the minimum key-value pair without removing it.
116
+ #
117
+ # @return [Array(Object, Object), nil] a two-element array [key, value], or nil if tree is empty
118
+ # @example
119
+ # tree = RBTree.new({3 => 'three', 1 => 'one', 2 => 'two'})
120
+ # tree.min # => [1, "one"]
121
+ def min = find_min
122
+
123
+ # Returns the maximum key-value pair without removing it.
124
+ #
125
+ # @return [Array(Object, Object), nil] a two-element array [key, value], or nil if tree is empty
126
+ # @example
127
+ # tree = RBTree.new({3 => 'three', 1 => 'one', 2 => 'two'})
128
+ # tree.max # => [3, "three"]
129
+ def max = find_max
130
+
135
131
  # Checks if the tree contains the given key.
136
132
  #
137
133
  # @param key [Object] the key to search for
@@ -158,63 +154,119 @@ class RBTree
158
154
  end
159
155
  alias_method :[], :get
160
156
 
161
- # Inserts or updates a key-value pair in the tree.
157
+ # Returns the key-value pair with the key closest to the given key.
158
+ #
159
+ # This method requires keys to be numeric or support subtraction and abs methods.
160
+ # If multiple keys have the same distance, the one with the smaller key is returned.
161
+ #
162
+ # @param key [Numeric] the target key
163
+ # @return [Array(Object, Object), nil] a two-element array [key, value], or nil if tree is empty
164
+ # @example
165
+ # tree = RBTree.new({1 => 'one', 5 => 'five', 10 => 'ten'})
166
+ # tree.nearest(4) # => [5, "five"]
167
+ # tree.nearest(7) # => [5, "five"]
168
+ # tree.nearest(8) # => [10, "ten"]
169
+ def nearest(key)
170
+ return nil unless key.respond_to?(:-)
171
+ n = find_nearest_node(key)
172
+ n == @nil_node ? nil : n.pair
173
+ end
174
+
175
+ # Returns the key-value pair with the largest key that is smaller than the given key.
176
+ #
177
+ # If the key exists in the tree, returns the predecessor (previous element).
178
+ # If the key does not exist, returns the largest key-value pair with key < given key.
179
+ #
180
+ # @param key [Object] the reference key
181
+ # @return [Array(Object, Object), nil] a two-element array [key, value], or nil if no predecessor exists
182
+ # @example
183
+ # tree = RBTree.new({1 => 'one', 3 => 'three', 5 => 'five', 7 => 'seven'})
184
+ # tree.prev(5) # => [3, "three"]
185
+ # tree.prev(4) # => [3, "three"] (4 does not exist)
186
+ # tree.prev(1) # => nil (no predecessor)
187
+ def prev(key)
188
+ n = find_predecessor_node(key)
189
+ n == @nil_node ? nil : n.pair
190
+ end
191
+
192
+ # Returns the key-value pair with the smallest key that is larger than the given key.
193
+ #
194
+ # If the key exists in the tree, returns the successor (next element).
195
+ # If the key does not exist, returns the smallest key-value pair with key > given key.
196
+ #
197
+ # @param key [Object] the reference key
198
+ # @return [Array(Object, Object), nil] a two-element array [key, value], or nil if no successor exists
199
+ # @example
200
+ # tree = RBTree.new({1 => 'one', 3 => 'three', 5 => 'five', 7 => 'seven'})
201
+ # tree.succ(5) # => [7, "seven"]
202
+ # tree.succ(4) # => [5, "five"] (4 does not exist)
203
+ # tree.succ(7) # => nil (no successor)
204
+ def succ(key)
205
+ n = find_successor_node(key)
206
+ n == @nil_node ? nil : n.pair
207
+ end
208
+
209
+ # Inserts one or more key-value pairs into the tree.
210
+ #
211
+ # This method supports both single entry insertion and bulk insertion.
212
+ #
213
+ # Single insertion:
214
+ # insert(key, value, overwrite: true)
215
+ #
216
+ # Bulk insertion:
217
+ # insert(hash, overwrite: true)
218
+ # insert(array_of_pairs, overwrite: true)
219
+ # insert(enumerator, overwrite: true)
220
+ # insert { data_source }
162
221
  #
163
222
  # If the key already exists and overwrite is true (default), the value is updated.
164
223
  # If overwrite is false and the key exists, the operation returns nil without modification.
165
224
  #
166
- # @param key [Object] the key to insert (must implement <=>)
167
- # @param value [Object] the value to associate with the key
225
+ # @param args [Object] key (and value) or source object
168
226
  # @param overwrite [Boolean] whether to overwrite existing keys (default: true)
169
- # @return [Boolean, nil] true if inserted/updated, nil if key exists and overwrite is false
170
- # @example
171
- # tree = RBTree.new
172
- # tree.insert(1, 'one') # => true
173
- # tree.insert(1, 'ONE') # => true (overwrites)
174
- # tree.insert(1, 'uno', overwrite: false) # => nil (no change)
175
- # tree[2] = 'two' # using alias
176
- def insert(key, value, overwrite: true)
177
- if (node = @hash_index[key])
178
- return nil unless overwrite
179
- node.value = value
180
- return true
181
- end
182
- y = @nil_node
183
- x = @root
184
- while x != @nil_node
185
- y = x
186
- cmp = key <=> x.key
187
- if cmp == 0
188
- return nil unless overwrite
189
- x.value = value
190
- return true
191
- elsif cmp < 0
192
- x = x.left
227
+ # @yieldreturn [Object] data source for bulk insertion
228
+ # @return [Boolean, nil] true if inserted/updated, nil if key exists and overwrite is false (for single insert)
229
+ # @example Single insert
230
+ # tree.insert(1, 'one')
231
+ # @example Bulk insert from Hash
232
+ # tree.insert({1 => 'one', 2 => 'two'})
233
+ # @example Bulk insert from Array
234
+ # tree.insert([[1, 'one'], [2, 'two']])
235
+ def insert(*args, overwrite: true, &block)
236
+ if args.size == 2
237
+ key, value = args
238
+ insert_entry(key, value, overwrite: overwrite)
239
+ else
240
+ source = nil
241
+ if args.empty? && block_given?
242
+ source = yield
243
+ elsif args.size == 1
244
+ source = args[0]
245
+ elsif args.empty?
246
+ return # No-op
193
247
  else
194
- x = x.right
248
+ raise ArgumentError, "wrong number of arguments (given #{args.size}, expected 0..2)"
249
+ end
250
+
251
+ return if source.nil?
252
+
253
+ unless source.respond_to?(:each)
254
+ raise ArgumentError, "Source must be iterable"
255
+ end
256
+
257
+ source.each do |*pair|
258
+ key, value = nil, nil
259
+ if pair.size == 1 && pair[0].is_a?(Array)
260
+ key, value = pair[0]
261
+ raise ArgumentError, "Invalid pair size: #{pair[0].size} (expected 2)" unless pair[0].size == 2
262
+ elsif pair.size == 2
263
+ key, value = pair
264
+ else
265
+ raise ArgumentError, "Invalid pair format: #{pair.inspect}"
266
+ end
267
+ insert_entry(key, value, overwrite: overwrite)
195
268
  end
196
269
  end
197
- z = allocate_node(key, value, Node::RED, @nil_node, @nil_node, @nil_node)
198
- z.parent = y
199
- if y == @nil_node
200
- @root = z
201
- elsif (key <=> y.key) < 0
202
- y.left = z
203
- else
204
- y.right = z
205
- end
206
- z.left = @nil_node
207
- z.right = @nil_node
208
- z.color = Node::RED
209
- insert_fixup(z)
210
- @size += 1
211
-
212
- if @min_node == @nil_node || (key <=> @min_node.key) < 0
213
- @min_node = z
214
- end
215
-
216
- @hash_index[key] = z # Add to hash index
217
- true
218
270
  end
219
271
  alias_method :[]=, :insert
220
272
 
@@ -233,17 +285,6 @@ class RBTree
233
285
  value
234
286
  end
235
287
 
236
- # Removes all key-value pairs from the tree.
237
- #
238
- # @return [RBTree] self
239
- def clear
240
- @root = @nil_node
241
- @min_node = @nil_node
242
- @hash_index.clear
243
- @size = 0
244
- self
245
- end
246
-
247
288
  # Removes and returns the minimum key-value pair.
248
289
  #
249
290
  # @return [Array(Object, Object), nil] a two-element array [key, value], or nil if tree is empty
@@ -273,6 +314,17 @@ class RBTree
273
314
  result
274
315
  end
275
316
 
317
+ # Removes all key-value pairs from the tree.
318
+ #
319
+ # @return [RBTree] self
320
+ def clear
321
+ @root = @nil_node
322
+ @min_node = @nil_node
323
+ @hash_index.clear
324
+ @size = 0
325
+ self
326
+ end
327
+
276
328
  # Iterates over all key-value pairs in ascending (or descending) order.
277
329
  #
278
330
  # @param reverse [Boolean] if true, iterate in descending order (default: false)
@@ -296,28 +348,10 @@ class RBTree
296
348
  # end
297
349
  def each(reverse: false, safe: false, &block)
298
350
  return enum_for(:each, reverse: reverse, safe: safe) unless block_given?
299
- if safe
300
- if reverse
301
- pair = find_max
302
- while pair
303
- current_key = pair[0]
304
- yield pair[0], pair[1]
305
- pair = find_predecessor(current_key)
306
- end
307
- else
308
- pair = find_min
309
- while pair
310
- current_key = pair[0]
311
- yield pair[0], pair[1]
312
- pair = find_successor(current_key)
313
- end
314
- end
351
+ if reverse
352
+ traverse_all_desc(@root, safe: safe, &block)
315
353
  else
316
- if reverse
317
- traverse_desc(@root, &block)
318
- else
319
- traverse_asc(@root, &block)
320
- end
354
+ traverse_all_asc(@root, safe: safe, &block)
321
355
  end
322
356
  self
323
357
  end
@@ -343,22 +377,6 @@ class RBTree
343
377
  # @see #each
344
378
  def reverse_each(safe: false, &block) = each(reverse: true, safe: safe, &block)
345
379
 
346
- # Returns the minimum key-value pair without removing it.
347
- #
348
- # @return [Array(Object, Object), nil] a two-element array [key, value], or nil if tree is empty
349
- # @example
350
- # tree = RBTree.new({3 => 'three', 1 => 'one', 2 => 'two'})
351
- # tree.min # => [1, "one"]
352
- def min = find_min
353
-
354
- # Returns the maximum key-value pair without removing it.
355
- #
356
- # @return [Array(Object, Object), nil] a two-element array [key, value], or nil if tree is empty
357
- # @example
358
- # tree = RBTree.new({3 => 'three', 1 => 'one', 2 => 'two'})
359
- # tree.max # => [3, "three"]
360
- def max = find_max
361
-
362
380
  # Retrieves all key-value pairs with keys less than the specified key.
363
381
  #
364
382
  # @param key [Object] the upper bound (exclusive)
@@ -373,26 +391,10 @@ class RBTree
373
391
  # tree.lt(3, safe: true) { |k, _| tree.delete(k) if k.even? } # safe to delete
374
392
  def lt(key, reverse: false, safe: false, &block)
375
393
  return enum_for(:lt, key, reverse: reverse, safe: safe) unless block_given?
376
- if safe
377
- if reverse
378
- pair = find_predecessor(key)
379
- while pair
380
- current_key = pair[0]
381
- yield pair
382
- pair = find_predecessor(current_key)
383
- end
384
- else
385
- pair = find_min
386
- while pair && pair[0] < key
387
- current_key = pair[0]
388
- yield pair
389
- pair = find_successor(current_key)
390
- end
391
- end
392
- elsif reverse
393
- traverse_lt_desc(@root, key, &block)
394
+ if reverse
395
+ traverse_lt_desc(@root, key, safe: safe, &block)
394
396
  else
395
- traverse_lt(@root, key, &block)
397
+ traverse_lt_asc(@root, key, safe: safe, &block)
396
398
  end
397
399
  self
398
400
  end
@@ -410,26 +412,10 @@ class RBTree
410
412
  # tree.lte(3, reverse: true).first # => [3, "three"]
411
413
  def lte(key, reverse: false, safe: false, &block)
412
414
  return enum_for(:lte, key, reverse: reverse, safe: safe) unless block_given?
413
- if safe
414
- if reverse
415
- pair = @hash_index[key]&.pair || find_predecessor(key)
416
- while pair
417
- current_key = pair[0]
418
- yield pair
419
- pair = find_predecessor(current_key)
420
- end
421
- else
422
- pair = find_min
423
- while pair && pair[0] <= key
424
- current_key = pair[0]
425
- yield pair
426
- pair = succ(current_key)
427
- end
428
- end
429
- elsif reverse
430
- traverse_lte_desc(@root, key, &block)
415
+ if reverse
416
+ traverse_lte_desc(@root, key, safe: safe, &block)
431
417
  else
432
- traverse_lte(@root, key, &block)
418
+ traverse_lte_asc(@root, key, safe: safe, &block)
433
419
  end
434
420
  self
435
421
  end
@@ -447,26 +433,10 @@ class RBTree
447
433
  # tree.gt(2, reverse: true).first # => [4, "four"]
448
434
  def gt(key, reverse: false, safe: false, &block)
449
435
  return enum_for(:gt, key, reverse: reverse, safe: safe) unless block_given?
450
- if safe
451
- if reverse
452
- pair = find_max
453
- while pair && pair[0] > key
454
- current_key = pair[0]
455
- yield pair
456
- pair = find_predecessor(current_key)
457
- end
458
- else
459
- pair = find_successor(key)
460
- while pair
461
- current_key = pair[0]
462
- yield pair
463
- pair = find_successor(current_key)
464
- end
465
- end
466
- elsif reverse
467
- traverse_gt_desc(@root, key, &block)
436
+ if reverse
437
+ traverse_gt_desc(@root, key, safe: safe, &block)
468
438
  else
469
- traverse_gt(@root, key, &block)
439
+ traverse_gt_asc(@root, key, safe: safe, &block)
470
440
  end
471
441
  self
472
442
  end
@@ -484,26 +454,10 @@ class RBTree
484
454
  # tree.gte(2, reverse: true).first # => [4, "four"]
485
455
  def gte(key, reverse: false, safe: false, &block)
486
456
  return enum_for(:gte, key, reverse: reverse, safe: safe) unless block_given?
487
- if safe
488
- if reverse
489
- pair = find_max
490
- while pair && pair[0] >= key
491
- current_key = pair[0]
492
- yield pair
493
- pair = find_predecessor(current_key)
494
- end
495
- else
496
- pair = @hash_index[key]&.pair || find_successor(key)
497
- while pair
498
- current_key = pair[0]
499
- yield pair
500
- pair = find_successor(current_key)
501
- end
502
- end
503
- elsif reverse
504
- traverse_gte_desc(@root, key, &block)
457
+ if reverse
458
+ traverse_gte_desc(@root, key, safe: safe, &block)
505
459
  else
506
- traverse_gte(@root, key, &block)
460
+ traverse_gte_asc(@root, key, safe: safe, &block)
507
461
  end
508
462
  self
509
463
  end
@@ -524,82 +478,27 @@ class RBTree
524
478
  # tree.between(2, 4, reverse: true).first # => [4, "four"]
525
479
  def between(min, max, include_min: true, include_max: true, reverse: false, safe: false, &block)
526
480
  return enum_for(:between, min, max, include_min: include_min, include_max: include_max, reverse: reverse, safe: safe) unless block_given?
527
- if safe
528
- if reverse
529
- pair = include_max && @hash_index[max]&.pair || find_predecessor(max)
530
- while pair && pair[0] > min
531
- current_key = pair[0]
532
- yield pair
533
- pair = find_predecessor(current_key)
534
- end
535
- yield pair if pair && include_min && pair[0] == min
536
- else
537
- pair = include_min && @hash_index[min]&.pair || find_successor(min)
538
- while pair && pair[0] < max
539
- current_key = pair[0]
540
- yield pair
541
- pair = find_successor(current_key)
542
- end
543
- yield pair if pair && include_max && pair[0] == max
544
- end
545
- elsif reverse
546
- traverse_between_desc(@root, min, max, include_min, include_max, &block)
481
+ if reverse
482
+ traverse_between_desc(@root, min, max, include_min, include_max, safe: safe, &block)
547
483
  else
548
- traverse_between(@root, min, max, include_min, include_max, &block)
484
+ traverse_between_asc(@root, min, max, include_min, include_max, safe: safe, &block)
549
485
  end
550
486
  self
551
487
  end
552
488
 
553
- # Returns the key-value pair with the key closest to the given key.
554
- #
555
- # This method requires keys to be numeric or support subtraction and abs methods.
556
- # If multiple keys have the same distance, the one with the smaller key is returned.
557
- #
558
- # @param key [Numeric] the target key
559
- # @return [Array(Object, Object), nil] a two-element array [key, value], or nil if tree is empty
560
- # @example
561
- # tree = RBTree.new({1 => 'one', 5 => 'five', 10 => 'ten'})
562
- # tree.nearest(4) # => [5, "five"]
563
- # tree.nearest(7) # => [5, "five"]
564
- # tree.nearest(8) # => [10, "ten"]
565
- def nearest(key)
566
- return nil unless key.respond_to?(:-)
567
- n = find_nearest_node(key)
568
- n == @nil_node ? nil : n.pair
569
- end
570
-
571
- # Returns the key-value pair with the largest key that is smaller than the given key.
572
- #
573
- # If the key exists in the tree, returns the predecessor (previous element).
574
- # If the key does not exist, returns the largest key-value pair with key < given key.
575
- #
576
- # @param key [Object] the reference key
577
- # @return [Array(Object, Object), nil] a two-element array [key, value], or nil if no predecessor exists
578
- # @example
579
- # tree = RBTree.new({1 => 'one', 3 => 'three', 5 => 'five', 7 => 'seven'})
580
- # tree.prev(5) # => [3, "three"]
581
- # tree.prev(4) # => [3, "three"] (4 does not exist)
582
- # tree.prev(1) # => nil (no predecessor)
583
- def prev(key)
584
- n = find_predecessor_node(key)
585
- n == @nil_node ? nil : n.pair
586
- end
587
-
588
- # Returns the key-value pair with the smallest key that is larger than the given key.
489
+ # Returns a string representation of the tree.
589
490
  #
590
- # If the key exists in the tree, returns the successor (next element).
591
- # If the key does not exist, returns the smallest key-value pair with key > given key.
491
+ # Shows the first 5 entries and total size. Useful for debugging.
592
492
  #
593
- # @param key [Object] the reference key
594
- # @return [Array(Object, Object), nil] a two-element array [key, value], or nil if no successor exists
595
- # @example
596
- # tree = RBTree.new({1 => 'one', 3 => 'three', 5 => 'five', 7 => 'seven'})
597
- # tree.succ(5) # => [7, "seven"]
598
- # tree.succ(4) # => [5, "five"] (4 does not exist)
599
- # tree.succ(7) # => nil (no successor)
600
- def succ(key)
601
- n = find_successor_node(key)
602
- n == @nil_node ? nil : n.pair
493
+ # @return [String] a human-readable representation of the tree
494
+ def inspect
495
+ if @size > 0
496
+ content = first(5).map { |k, v| "#{k.inspect}=>#{v.inspect}" }.join(", ")
497
+ suffix = @size > 5 ? ", ..." : ""
498
+ "#<#{self.class}:0x#{object_id.to_s(16)} size=#{@size} {#{content}#{suffix}}>"
499
+ else
500
+ super
501
+ end
603
502
  end
604
503
 
605
504
  # Validates the red-black tree properties.
@@ -618,46 +517,188 @@ class RBTree
618
517
  true
619
518
  end
620
519
 
621
- # @!visibility private
622
- private
623
-
624
- # Traverses the tree in ascending order (in-order traversal).
520
+ # @!visibility protected
521
+ protected
522
+
523
+ # Inserts a single key-value pair.
524
+ #
525
+ # @param key [Object] the key to insert
526
+ # @param value [Object] the value to associate with the key
527
+ # @param overwrite [Boolean] whether to overwrite existing keys (default: true)
528
+ # @return [Boolean, nil] true if inserted/updated, nil if key exists and overwrite is false
529
+ def insert_entry(key, value, overwrite: true)
530
+ if (node = @hash_index[key])
531
+ return nil unless overwrite
532
+ node.value = value
533
+ return true
534
+ end
535
+ y = @nil_node
536
+ x = @root
537
+ while x != @nil_node
538
+ y = x
539
+ cmp = key <=> x.key
540
+ if cmp == 0
541
+ return nil unless overwrite
542
+ x.value = value
543
+ return true
544
+ elsif cmp < 0
545
+ x = x.left
546
+ else
547
+ x = x.right
548
+ end
549
+ end
550
+ z = allocate_node(key, value, Node::RED, @nil_node, @nil_node, @nil_node)
551
+ z.parent = y
552
+ if y == @nil_node
553
+ @root = z
554
+ elsif (key <=> y.key) < 0
555
+ y.left = z
556
+ else
557
+ y.right = z
558
+ end
559
+ z.left = @nil_node
560
+ z.right = @nil_node
561
+ z.color = Node::RED
562
+ insert_fixup(z)
563
+ @size += 1
564
+
565
+ if @min_node == @nil_node || (key <=> @min_node.key) < 0
566
+ @min_node = z
567
+ end
568
+
569
+ @hash_index[key] = z # Add to hash index
570
+ true
571
+ end
572
+
573
+ # Traverses the tree in ascending order (in-order traversal).
574
+ #
575
+ # @param node [Node] the current node
576
+ # @param min [Object] the lower bound (inclusive)
577
+ # @param max [Object] the upper bound (inclusive)
578
+ # @param include_min [Boolean] whether to include the lower bound
579
+ # @param include_max [Boolean] whether to include the upper bound
580
+ # @param safe [Boolean] whether to use safe traversal
581
+ # @yield [key, value] each key-value pair in ascending order
582
+ # @return [void]
583
+ def traverse_range_asc(node, min, max, include_min, include_max, safe: false, &block)
584
+ if safe
585
+ pair = !min ? find_min :
586
+ include_min && @hash_index[min]&.pair || find_successor(min)
587
+ if !max
588
+ while pair
589
+ current_key = pair[0]
590
+ yield pair
591
+ pair = find_successor(current_key)
592
+ end
593
+ else
594
+ while pair && pair[0] < max
595
+ current_key = pair[0]
596
+ yield pair
597
+ pair = find_successor(current_key)
598
+ end
599
+ end
600
+ yield pair if pair && max && include_max && pair[0] == max
601
+ else
602
+ stack = []
603
+ current = node
604
+ while current != @nil_node || !stack.empty?
605
+ while current != @nil_node
606
+ if min && ((current.key <=> min) < 0 ||
607
+ (!include_min && (current.key <=> min) == 0))
608
+ current = current.right
609
+ else
610
+ stack << current
611
+ current = current.left
612
+ end
613
+ end
614
+
615
+ if !stack.empty?
616
+ current = stack.pop
617
+
618
+ if max && ((current.key <=> max) > 0 ||
619
+ (!include_max && (current.key <=> max) == 0))
620
+ return
621
+ else
622
+ yield current.pair
623
+ current = current.right
624
+ end
625
+ end
626
+ end
627
+ end
628
+ end
629
+
630
+ # Traverses the tree in descending order (reverse in-order traversal).
625
631
  #
626
632
  # @param node [Node] the current node
627
- # @yield [key, value] each key-value pair in ascending order
633
+ # @param min [Object] the lower bound (inclusive)
634
+ # @param max [Object] the upper bound (inclusive)
635
+ # @param include_min [Boolean] whether to include the lower bound
636
+ # @param include_max [Boolean] whether to include the upper bound
637
+ # @param safe [Boolean] whether to use safe traversal
638
+ # @yield [key, value] each key-value pair in descending order
628
639
  # @return [void]
629
- def traverse_asc(node, &block)
630
- stack = []
631
- current = node
632
- while current != @nil_node || !stack.empty?
633
- while current != @nil_node
634
- stack << current
635
- current = current.left
640
+ def traverse_range_desc(node, min, max, include_min, include_max, safe: false, &block)
641
+ if safe
642
+ pair = !max ? find_max :
643
+ include_max && @hash_index[max]&.pair || find_predecessor(max)
644
+ if !min
645
+ while pair
646
+ current_key = pair[0]
647
+ yield pair
648
+ pair = find_predecessor(current_key)
649
+ end
650
+ else
651
+ while pair && pair[0] > min
652
+ current_key = pair[0]
653
+ yield pair
654
+ pair = find_predecessor(current_key)
655
+ end
656
+ end
657
+ yield pair if pair && min && include_min && pair[0] == min
658
+ else
659
+ stack = []
660
+ current = node
661
+ while current != @nil_node || !stack.empty?
662
+ while current != @nil_node
663
+ if max && ((current.key <=> max) > 0 ||
664
+ (!include_max && (current.key <=> max) == 0))
665
+ current = current.left
666
+ else
667
+ stack << current
668
+ current = current.right
669
+ end
670
+ end
671
+
672
+ if !stack.empty?
673
+ current = stack.pop
674
+
675
+ if min && ((current.key <=> min) < 0 ||
676
+ (!include_min && (current.key <=> min) == 0))
677
+ return
678
+ else
679
+ yield current.pair
680
+ current = current.left
681
+ end
682
+ end
636
683
  end
637
- current = stack.pop
638
- yield current.pair
639
- current = current.right
640
684
  end
641
685
  end
642
686
 
687
+ # Traverses the tree in ascending order (in-order traversal).
688
+ #
689
+ # @param node [Node] the current node
690
+ # @yield [key, value] each key-value pair in ascending order
691
+ # @return [void]
692
+ def traverse_all_asc(node, safe: false, &block) =
693
+ traverse_range_asc(node, nil, nil, false, false, safe: safe, &block)
694
+
643
695
  # Traverses the tree in descending order (reverse in-order traversal).
644
696
  #
645
697
  # @param node [Node] the current node
646
698
  # @yield [key, value] each key-value pair in descending order
647
699
  # @return [void]
648
- def traverse_desc(node, &block)
649
- stack = []
650
- current = node
651
- while current != @nil_node || !stack.empty?
652
- while current != @nil_node
653
- stack << current
654
- current = current.right
655
- end
656
- current = stack.pop
657
- yield current.pair
658
- current = current.left
659
- end
660
- end
700
+ def traverse_all_desc(node, safe: false, &block) =
701
+ traverse_range_desc(node, nil, nil, false, false, safe: safe, &block)
661
702
 
662
703
  # Traverses nodes with keys less than the specified key.
663
704
  #
@@ -665,15 +706,8 @@ class RBTree
665
706
  # @param key [Object] the upper bound (exclusive)
666
707
  # @yield [key, value] each matching key-value pair
667
708
  # @return [void]
668
- def traverse_lt(node, key, &block)
669
- return if node == @nil_node
670
-
671
- traverse_lt(node.left, key, &block)
672
- if (node.key <=> key) < 0
673
- yield node.pair
674
- traverse_lt(node.right, key, &block)
675
- end
676
- end
709
+ def traverse_lt_asc(node, key, safe: false, &block) =
710
+ traverse_range_asc(node, nil, key, false, false, safe: safe, &block)
677
711
 
678
712
  # Traverses nodes with keys less than or equal to the specified key.
679
713
  #
@@ -681,15 +715,8 @@ class RBTree
681
715
  # @param key [Object] the upper bound (inclusive)
682
716
  # @yield [key, value] each matching key-value pair
683
717
  # @return [void]
684
- def traverse_lte(node, key, &block)
685
- return if node == @nil_node
686
-
687
- traverse_lte(node.left, key, &block)
688
- if (node.key <=> key) <= 0
689
- yield node.pair
690
- traverse_lte(node.right, key, &block)
691
- end
692
- end
718
+ def traverse_lte_asc(node, key, safe: false, &block) =
719
+ traverse_range_asc(node, nil, key, false, true, safe: safe, &block)
693
720
 
694
721
  # Traverses nodes with keys greater than the specified key.
695
722
  #
@@ -697,15 +724,8 @@ class RBTree
697
724
  # @param key [Object] the lower bound (exclusive)
698
725
  # @yield [key, value] each matching key-value pair
699
726
  # @return [void]
700
- def traverse_gt(node, key, &block)
701
- return if node == @nil_node
702
-
703
- if (node.key <=> key) > 0
704
- traverse_gt(node.left, key, &block)
705
- yield node.pair
706
- end
707
- traverse_gt(node.right, key, &block)
708
- end
727
+ def traverse_gt_asc(node, key, safe: false, &block) =
728
+ traverse_range_asc(node, key, nil, false, false, safe: safe, &block)
709
729
 
710
730
  # Traverses nodes with keys greater than or equal to the specified key.
711
731
  #
@@ -713,15 +733,8 @@ class RBTree
713
733
  # @param key [Object] the lower bound (inclusive)
714
734
  # @yield [key, value] each matching key-value pair
715
735
  # @return [void]
716
- def traverse_gte(node, key, &block)
717
- return if node == @nil_node
718
-
719
- if (node.key <=> key) >= 0
720
- traverse_gte(node.left, key, &block)
721
- yield node.pair
722
- end
723
- traverse_gte(node.right, key, &block)
724
- end
736
+ def traverse_gte_asc(node, key, safe: false, &block) =
737
+ traverse_range_asc(node, key, nil, true, false, safe: safe, &block)
725
738
 
726
739
  # Traverses nodes with keys within the specified range.
727
740
  #
@@ -732,23 +745,8 @@ class RBTree
732
745
  # @param include_max [Boolean] whether to include the upper bound
733
746
  # @yield [key, value] each matching key-value pair
734
747
  # @return [void]
735
- def traverse_between(node, min, max, include_min, include_max, &block)
736
- return if node == @nil_node
737
- if (node.key <=> min) > 0
738
- traverse_between(node.left, min, max, include_min, include_max, &block)
739
- end
740
-
741
- greater = include_min ? (node.key <=> min) >= 0 : (node.key <=> min) > 0
742
- less = include_max ? (node.key <=> max) <= 0 : (node.key <=> max) < 0
743
-
744
- if greater && less
745
- yield node.pair
746
- end
747
-
748
- if (node.key <=> max) < 0
749
- traverse_between(node.right, min, max, include_min, include_max, &block)
750
- end
751
- end
748
+ def traverse_between_asc(node, min, max, include_min, include_max, safe: false, &block) =
749
+ traverse_range_asc(node, min, max, include_min, include_max, safe: safe, &block)
752
750
 
753
751
  # Traverses nodes with keys less than the specified key in descending order.
754
752
  #
@@ -756,15 +754,8 @@ class RBTree
756
754
  # @param key [Object] the upper bound (exclusive)
757
755
  # @yield [key, value] each matching key-value pair in descending order
758
756
  # @return [void]
759
- def traverse_lt_desc(node, key, &block)
760
- return if node == @nil_node
761
-
762
- if (node.key <=> key) < 0
763
- traverse_lt_desc(node.right, key, &block)
764
- yield node.pair
765
- end
766
- traverse_lt_desc(node.left, key, &block)
767
- end
757
+ def traverse_lt_desc(node, key, safe: false, &block) =
758
+ traverse_range_desc(node, nil, key, false, false, safe: safe, &block)
768
759
 
769
760
  # Traverses nodes with keys less than or equal to the specified key in descending order.
770
761
  #
@@ -772,15 +763,8 @@ class RBTree
772
763
  # @param key [Object] the upper bound (inclusive)
773
764
  # @yield [key, value] each matching key-value pair in descending order
774
765
  # @return [void]
775
- def traverse_lte_desc(node, key, &block)
776
- return if node == @nil_node
777
-
778
- if (node.key <=> key) <= 0
779
- traverse_lte_desc(node.right, key, &block)
780
- yield node.pair
781
- end
782
- traverse_lte_desc(node.left, key, &block)
783
- end
766
+ def traverse_lte_desc(node, key, safe: false, &block) =
767
+ traverse_range_desc(node, nil, key, false, true, safe: safe, &block)
784
768
 
785
769
  # Traverses nodes with keys greater than the specified key in descending order.
786
770
  #
@@ -788,15 +772,8 @@ class RBTree
788
772
  # @param key [Object] the lower bound (exclusive)
789
773
  # @yield [key, value] each matching key-value pair in descending order
790
774
  # @return [void]
791
- def traverse_gt_desc(node, key, &block)
792
- return if node == @nil_node
793
-
794
- traverse_gt_desc(node.right, key, &block)
795
- if (node.key <=> key) > 0
796
- yield node.pair
797
- traverse_gt_desc(node.left, key, &block)
798
- end
799
- end
775
+ def traverse_gt_desc(node, key, safe: false, &block) =
776
+ traverse_range_desc(node, key, nil, false, false, safe: safe, &block)
800
777
 
801
778
  # Traverses nodes with keys greater than or equal to the specified key in descending order.
802
779
  #
@@ -804,15 +781,8 @@ class RBTree
804
781
  # @param key [Object] the lower bound (inclusive)
805
782
  # @yield [key, value] each matching key-value pair in descending order
806
783
  # @return [void]
807
- def traverse_gte_desc(node, key, &block)
808
- return if node == @nil_node
809
-
810
- traverse_gte_desc(node.right, key, &block)
811
- if (node.key <=> key) >= 0
812
- yield node.pair
813
- traverse_gte_desc(node.left, key, &block)
814
- end
815
- end
784
+ def traverse_gte_desc(node, key, safe: false, &block) =
785
+ traverse_range_desc(node, key, nil, true, false, safe: safe, &block)
816
786
 
817
787
  # Traverses nodes with keys within the specified range in descending order.
818
788
  #
@@ -823,24 +793,8 @@ class RBTree
823
793
  # @param include_max [Boolean] whether to include the upper bound
824
794
  # @yield [key, value] each matching key-value pair in descending order
825
795
  # @return [void]
826
- def traverse_between_desc(node, min, max, include_min, include_max, &block)
827
- return if node == @nil_node
828
-
829
- if (node.key <=> max) < 0
830
- traverse_between_desc(node.right, min, max, include_min, include_max, &block)
831
- end
832
-
833
- greater = include_min ? (node.key <=> min) >= 0 : (node.key <=> min) > 0
834
- less = include_max ? (node.key <=> max) <= 0 : (node.key <=> max) < 0
835
-
836
- if greater && less
837
- yield node.pair
838
- end
839
-
840
- if (node.key <=> min) > 0
841
- traverse_between_desc(node.left, min, max, include_min, include_max, &block)
842
- end
843
- end
796
+ def traverse_between_desc(node, min, max, include_min, include_max, safe: false, &block) =
797
+ traverse_range_desc(node, min, max, include_min, include_max, safe: safe, &block)
844
798
 
845
799
  # Restores red-black tree properties after insertion.
846
800
  #
@@ -1407,6 +1361,17 @@ end
1407
1361
  # @author Masahito Suzuki
1408
1362
  # @since 0.1.2
1409
1363
  class MultiRBTree < RBTree
1364
+ def min(last: false)
1365
+ return nil if @min_node == @nil_node || @min_node.value.empty?
1366
+ [@min_node.key, last ? @min_node.value.last : @min_node.value.first]
1367
+ end
1368
+
1369
+ def max(last: false)
1370
+ n = rightmost(@root)
1371
+ return nil if n == @nil_node || n.value.empty?
1372
+ [n.key, last ? n.value.last : n.value.first]
1373
+ end
1374
+
1410
1375
  # Retrieves a value associated with the given key.
1411
1376
  #
1412
1377
  # @param key [Object] the key to look up
@@ -1436,26 +1401,22 @@ class MultiRBTree < RBTree
1436
1401
  # @return [Object, nil] the last value for the key, or nil if not found
1437
1402
  def get_last(key) = get(key, last: true)
1438
1403
 
1439
- # Returns the first value for the given key (for Hash-like access).
1440
- #
1441
- # Note: Unlike get(), this method does not accept options.
1442
- #
1443
- # @param key [Object] the key to look up
1444
- # @return [Object, nil] the first value for the key, or nil if not found
1445
- def [](key) = get(key)
1404
+ def nearest(key, last: false)
1405
+ n = find_nearest_node(key)
1406
+ return nil if n == @nil_node || n.value.empty?
1407
+ [n.key, last ? n.value.last : n.value.first]
1408
+ end
1446
1409
 
1447
- # Retrieves all values associated with the given key.
1448
- #
1449
- # @param key [Object] the key to look up
1450
- # @return [Array, nil] an Array containing all values, or nil if not found
1451
- # @example
1452
- # tree = MultiRBTree.new
1453
- # tree.insert(1, 'first')
1454
- # tree.insert(1, 'second')
1455
- # tree.get_all(1).to_a # => ["first", "second"]
1456
- def get_all(key)
1457
- return enum_for(:get_all, key) unless block_given?
1458
- @hash_index[key]&.value&.each { |v| yield v }
1410
+ def prev(key, last: false)
1411
+ pair = super(key)
1412
+ return nil unless pair
1413
+ [pair[0], last ? pair[1].last : pair[1].first]
1414
+ end
1415
+
1416
+ def succ(key, last: false)
1417
+ pair = super(key)
1418
+ return nil unless pair
1419
+ [pair[0], last ? pair[1].last : pair[1].first]
1459
1420
  end
1460
1421
 
1461
1422
  # Inserts a value for the given key.
@@ -1465,12 +1426,13 @@ class MultiRBTree < RBTree
1465
1426
  #
1466
1427
  # @param key [Object] the key (must implement <=>)
1467
1428
  # @param value [Object] the value to insert
1429
+ # @param overwrite [Boolean] ignored for MultiRBTree which always appends
1468
1430
  # @return [Boolean] always returns true
1469
1431
  # @example
1470
1432
  # tree = MultiRBTree.new
1471
1433
  # tree.insert(1, 'first')
1472
1434
  # tree.insert(1, 'second') # adds another value for key 1
1473
- def insert(key, value)
1435
+ def insert_entry(key, value, **)
1474
1436
  if (node = @hash_index[key])
1475
1437
  node.value << value
1476
1438
  @size += 1
@@ -1583,7 +1545,7 @@ class MultiRBTree < RBTree
1583
1545
  node.value.shift
1584
1546
  @size -= 1
1585
1547
  if node.value.empty?
1586
- remove_node(node)
1548
+ delete_node(key)
1587
1549
  end
1588
1550
  [key, val]
1589
1551
  end
@@ -1591,246 +1553,39 @@ class MultiRBTree < RBTree
1591
1553
  def pop
1592
1554
  n = rightmost(@root)
1593
1555
  return nil if n == @nil_node
1556
+ key = n.key
1594
1557
  val = n.value.last
1595
1558
  n.value.pop
1596
1559
  @size -= 1
1597
1560
  if n.value.empty?
1598
- remove_node(n)
1599
- end
1600
- [n.key, val]
1601
- end
1602
-
1603
- def min(last: false)
1604
- return nil if @min_node == @nil_node || @min_node.value.empty?
1605
- [@min_node.key, last ? @min_node.value.last : @min_node.value.first]
1606
- end
1607
-
1608
- def max(last: false)
1609
- n = rightmost(@root)
1610
- return nil if n == @nil_node || n.value.empty?
1611
- [n.key, last ? n.value.last : n.value.first]
1612
- end
1613
-
1614
- def nearest(key, last: false)
1615
- n = find_nearest_node(key)
1616
- return nil if n == @nil_node || n.value.empty?
1617
- [n.key, last ? n.value.last : n.value.first]
1618
- end
1619
-
1620
- def each(reverse: false, safe: false, &block)
1621
- return enum_for(:each, reverse: reverse, safe: safe) unless block_given?
1622
- if safe
1623
- super do |k, vals|
1624
- vals.send(reverse ? :reverse_each : :each) { |v| yield k, v }
1625
- end
1626
- else
1627
- super
1628
- end
1629
- end
1630
-
1631
- def lt(key, reverse: false, safe: false, &block)
1632
- return enum_for(:lt, key, reverse: reverse, safe: safe) unless block_given?
1633
- if safe
1634
- super do |k, vals|
1635
- vals.send(reverse ? :reverse_each : :each) { |v| yield k, v }
1636
- end
1637
- else
1638
- super
1639
- end
1640
- end
1641
-
1642
- def lte(key, reverse: false, safe: false, &block)
1643
- return enum_for(:lte, key, reverse: reverse, safe: safe) unless block_given?
1644
- if safe
1645
- super do |k, vals|
1646
- vals.send(reverse ? :reverse_each : :each) { |v| yield k, v }
1647
- end
1648
- else
1649
- super
1650
- end
1651
- end
1652
-
1653
- def gt(key, reverse: false, safe: false, &block)
1654
- return enum_for(:gt, key, reverse: reverse, safe: safe) unless block_given?
1655
- if safe
1656
- super do |k, vals|
1657
- vals.send(reverse ? :reverse_each : :each) { |v| yield k, v }
1658
- end
1659
- else
1660
- super
1661
- end
1662
- end
1663
-
1664
- def gte(key, reverse: false, safe: false, &block)
1665
- return enum_for(:gte, key, reverse: reverse, safe: safe) unless block_given?
1666
- if safe
1667
- super do |k, vals|
1668
- vals.send(reverse ? :reverse_each : :each) { |v| yield k, v }
1669
- end
1670
- else
1671
- super
1672
- end
1673
- end
1674
-
1675
- def between(min, max, include_min: true, include_max: true, reverse: false, safe: false, &block)
1676
- return enum_for(:between, min, max, include_min: include_min, include_max: include_max, reverse: reverse, safe: safe) unless block_given?
1677
- if safe
1678
- super do |k, vals|
1679
- vals.send(reverse ? :reverse_each : :each) { |v| yield k, v }
1680
- end
1681
- else
1682
- super
1683
- end
1684
- end
1685
-
1686
- def prev(key, last: false) = (n = super) && [n.key, last ? n.value.last : n.value.first]
1687
- def succ(key, last: false) = (n = super) && [n.key, last ? n.value.last : n.value.first]
1688
-
1689
- private
1690
-
1691
- def traverse_asc(node, &block)
1692
- stack = []
1693
- current = node
1694
- while current != @nil_node || !stack.empty?
1695
- while current != @nil_node
1696
- stack << current
1697
- current = current.left
1698
- end
1699
- current = stack.pop
1700
- current.value.each { |v| yield current.key, v }
1701
- current = current.right
1702
- end
1703
- end
1704
-
1705
- def traverse_desc(node, &block)
1706
- stack = []
1707
- current = node
1708
- while current != @nil_node || !stack.empty?
1709
- while current != @nil_node
1710
- stack << current
1711
- current = current.right
1712
- end
1713
- current = stack.pop
1714
- current.value.reverse_each { |v| yield current.key, v }
1715
- current = current.left
1716
- end
1717
- end
1718
-
1719
- def traverse_lt(node, key, &block)
1720
- return if node == @nil_node
1721
-
1722
- traverse_lt(node.left, key, &block)
1723
- if (node.key <=> key) < 0
1724
- node.value.each { |v| yield node.key, v }
1725
- traverse_lt(node.right, key, &block)
1726
- end
1727
- end
1728
-
1729
- def traverse_lte(node, key, &block)
1730
- return if node == @nil_node
1731
-
1732
- traverse_lte(node.left, key, &block)
1733
- if (node.key <=> key) <= 0
1734
- node.value.each { |v| yield node.key, v }
1735
- traverse_lte(node.right, key, &block)
1736
- end
1737
- end
1738
-
1739
- def traverse_gt(node, key, &block)
1740
- return if node == @nil_node
1741
-
1742
- if (node.key <=> key) > 0
1743
- traverse_gt(node.left, key, &block)
1744
- node.value.each { |v| yield node.key, v }
1745
- end
1746
- traverse_gt(node.right, key, &block)
1747
- end
1748
-
1749
- def traverse_gte(node, key, &block)
1750
- return if node == @nil_node
1751
-
1752
- if (node.key <=> key) >= 0
1753
- traverse_gte(node.left, key, &block)
1754
- node.value.each { |v| yield node.key, v }
1755
- end
1756
- traverse_gte(node.right, key, &block)
1757
- end
1758
-
1759
- def traverse_between(node, min, max, include_min, include_max, &block)
1760
- return if node == @nil_node
1761
- if (node.key <=> min) > 0
1762
- traverse_between(node.left, min, max, include_min, include_max, &block)
1763
- end
1764
-
1765
- greater = include_min ? (node.key <=> min) >= 0 : (node.key <=> min) > 0
1766
- less = include_max ? (node.key <=> max) <= 0 : (node.key <=> max) < 0
1767
-
1768
- if greater && less
1769
- node.value.each { |v| yield node.key, v }
1770
- end
1771
-
1772
- if (node.key <=> max) < 0
1773
- traverse_between(node.right, min, max, include_min, include_max, &block)
1774
- end
1775
- end
1776
-
1777
- def traverse_lt_desc(node, key, &block)
1778
- return if node == @nil_node
1779
-
1780
- if (node.key <=> key) < 0
1781
- traverse_lt_desc(node.right, key, &block)
1782
- node.value.reverse_each { |v| yield node.key, v }
1561
+ delete_node(key)
1783
1562
  end
1784
- traverse_lt_desc(node.left, key, &block)
1563
+ [key, val]
1785
1564
  end
1786
1565
 
1787
- def traverse_lte_desc(node, key, &block)
1788
- return if node == @nil_node
1789
-
1790
- if (node.key <=> key) <= 0
1791
- traverse_lte_desc(node.right, key, &block)
1792
- node.value.reverse_each { |v| yield node.key, v }
1793
- end
1794
- traverse_lte_desc(node.left, key, &block)
1566
+ # Retrieves all values associated with the given key.
1567
+ #
1568
+ # @param key [Object] the key to look up
1569
+ # @return [Array, nil] an Array containing all values, or nil if not found
1570
+ # @example
1571
+ # tree = MultiRBTree.new
1572
+ # tree.insert(1, 'first')
1573
+ # tree.insert(1, 'second')
1574
+ # tree.get_all(1).to_a # => ["first", "second"]
1575
+ def get_all(key)
1576
+ return enum_for(:get_all, key) unless block_given?
1577
+ @hash_index[key]&.value&.each { |v| yield v }
1795
1578
  end
1796
1579
 
1797
- def traverse_gt_desc(node, key, &block)
1798
- return if node == @nil_node
1799
-
1800
- traverse_gt_desc(node.right, key, &block)
1801
- if (node.key <=> key) > 0
1802
- node.value.reverse_each { |v| yield node.key, v }
1803
- traverse_gt_desc(node.left, key, &block)
1804
- end
1805
- end
1580
+ # @!visibility protected
1581
+ protected
1806
1582
 
1807
- def traverse_gte_desc(node, key, &block)
1808
- return if node == @nil_node
1809
-
1810
- traverse_gte_desc(node.right, key, &block)
1811
- if (node.key <=> key) >= 0
1812
- node.value.reverse_each { |v| yield node.key, v }
1813
- traverse_gte_desc(node.left, key, &block)
1814
- end
1583
+ def traverse_range_asc(...)
1584
+ super { |k, vals| vals.each { |v| yield k, v } }
1815
1585
  end
1816
1586
 
1817
- def traverse_between_desc(node, min, max, include_min, include_max, &block)
1818
- return if node == @nil_node
1819
-
1820
- if (node.key <=> max) < 0
1821
- traverse_between_desc(node.right, min, max, include_min, include_max, &block)
1822
- end
1823
-
1824
- greater = include_min ? (node.key <=> min) >= 0 : (node.key <=> min) > 0
1825
- less = include_max ? (node.key <=> max) <= 0 : (node.key <=> max) < 0
1826
-
1827
- if greater && less
1828
- node.value.reverse_each { |v| yield node.key, v }
1829
- end
1830
-
1831
- if (node.key <=> min) > 0
1832
- traverse_between_desc(node.left, min, max, include_min, include_max, &block)
1833
- end
1587
+ def traverse_range_desc(...)
1588
+ super { |k, vals| vals.reverse_each { |v| yield k, v } }
1834
1589
  end
1835
1590
  end
1836
1591
 
@@ -1878,14 +1633,6 @@ class RBTree::Node
1878
1633
  @parent = parent
1879
1634
  end
1880
1635
 
1881
- # Checks if the node is red.
1882
- # @return [Boolean] true if red, false otherwise
1883
- def red? = @color == RED
1884
-
1885
- # Checks if the node is black.
1886
- # @return [Boolean] true if black, false otherwise
1887
- def black? = @color == BLACK
1888
-
1889
1636
  # Returns the key-value pair.
1890
1637
  # @return [Array(Object, Object)] the key-value pair
1891
1638
  def pair = [key, value]