rbtree-ruby 0.2.1 → 0.2.2
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/CHANGELOG.md +13 -0
- data/lib/rbtree/version.rb +1 -1
- data/lib/rbtree.rb +294 -598
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 13b088e9f0f8ab5cf80a77b8f9b8e1af73b94b33bdff90115fe575def2c54b11
|
|
4
|
+
data.tar.gz: 51636a7c22c4ccc70d2ac14bafc58a39bbccac7599a704506c280d8d39345117
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: e543801d0b22de4ee8654f7b8164121c2107ccda64bc16f47d034e98526703e4aa444e03cecd225bddb9aa9fc5547813bcd1bc73cd4a4048df98eee5d41a2fc6
|
|
7
|
+
data.tar.gz: 6d6986550fe2293e971558e65119f230c3eb26e8f43f8af77fe8bf666d5df337c6bf23e36a4e4fd7e8aee86287b6f58579e48a637e66d27a6e80ab66b0010ed4
|
data/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,19 @@ All notable changes to this project will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [0.2.2] - 2026-01-14
|
|
9
|
+
|
|
10
|
+
### Changed
|
|
11
|
+
- **Iterative Traversal (Complete)**: All traversal methods (`lt`, `lte`, `gt`, `gte`, `between` and their `_desc` variants) now use an iterative stack-based approach instead of recursion.
|
|
12
|
+
- Ensures deep trees can be traversed without `SystemStackError`.
|
|
13
|
+
- Applies to both `RBTree` and `MultiRBTree`.
|
|
14
|
+
- **Code Deduplication**: Unified traversal logic between `RBTree` and `MultiRBTree` for better maintainability.
|
|
15
|
+
- **Documentation**: Minor typo fixes.
|
|
16
|
+
|
|
17
|
+
### Fixed
|
|
18
|
+
- **MultiRBTree#prev / #succ**: Fixed incorrect use of bare `super` which forwarded keyword arguments to parent methods that don't accept them. Also fixed incorrect access to parent return value (was treating `[key, value]` pair as a node object).
|
|
19
|
+
- **MultiRBTree#shift / #pop hash index leak**: When `shift` or `pop` removed the last value for a key, the key remained in the internal hash index (`@hash_index`). Now correctly uses `delete_node(key)` instead of `remove_node(node)` to ensure hash index consistency.
|
|
20
|
+
|
|
8
21
|
## [0.2.1] - 2026-01-14
|
|
9
22
|
|
|
10
23
|
### Added
|
data/lib/rbtree/version.rb
CHANGED
data/lib/rbtree.rb
CHANGED
|
@@ -112,26 +112,27 @@ class RBTree
|
|
|
112
112
|
end
|
|
113
113
|
end
|
|
114
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
|
|
127
|
-
end
|
|
128
|
-
end
|
|
129
|
-
|
|
130
115
|
# Checks if the tree is empty.
|
|
131
116
|
#
|
|
132
117
|
# @return [Boolean] true if the tree contains no elements, false otherwise
|
|
133
118
|
def empty? = @root == @nil_node
|
|
134
119
|
|
|
120
|
+
# Returns the minimum key-value pair without removing it.
|
|
121
|
+
#
|
|
122
|
+
# @return [Array(Object, Object), nil] a two-element array [key, value], or nil if tree is empty
|
|
123
|
+
# @example
|
|
124
|
+
# tree = RBTree.new({3 => 'three', 1 => 'one', 2 => 'two'})
|
|
125
|
+
# tree.min # => [1, "one"]
|
|
126
|
+
def min = find_min
|
|
127
|
+
|
|
128
|
+
# Returns the maximum key-value pair without removing it.
|
|
129
|
+
#
|
|
130
|
+
# @return [Array(Object, Object), nil] a two-element array [key, value], or nil if tree is empty
|
|
131
|
+
# @example
|
|
132
|
+
# tree = RBTree.new({3 => 'three', 1 => 'one', 2 => 'two'})
|
|
133
|
+
# tree.max # => [3, "three"]
|
|
134
|
+
def max = find_max
|
|
135
|
+
|
|
135
136
|
# Checks if the tree contains the given key.
|
|
136
137
|
#
|
|
137
138
|
# @param key [Object] the key to search for
|
|
@@ -158,6 +159,58 @@ class RBTree
|
|
|
158
159
|
end
|
|
159
160
|
alias_method :[], :get
|
|
160
161
|
|
|
162
|
+
# Returns the key-value pair with the key closest to the given key.
|
|
163
|
+
#
|
|
164
|
+
# This method requires keys to be numeric or support subtraction and abs methods.
|
|
165
|
+
# If multiple keys have the same distance, the one with the smaller key is returned.
|
|
166
|
+
#
|
|
167
|
+
# @param key [Numeric] the target key
|
|
168
|
+
# @return [Array(Object, Object), nil] a two-element array [key, value], or nil if tree is empty
|
|
169
|
+
# @example
|
|
170
|
+
# tree = RBTree.new({1 => 'one', 5 => 'five', 10 => 'ten'})
|
|
171
|
+
# tree.nearest(4) # => [5, "five"]
|
|
172
|
+
# tree.nearest(7) # => [5, "five"]
|
|
173
|
+
# tree.nearest(8) # => [10, "ten"]
|
|
174
|
+
def nearest(key)
|
|
175
|
+
return nil unless key.respond_to?(:-)
|
|
176
|
+
n = find_nearest_node(key)
|
|
177
|
+
n == @nil_node ? nil : n.pair
|
|
178
|
+
end
|
|
179
|
+
|
|
180
|
+
# Returns the key-value pair with the largest key that is smaller than the given key.
|
|
181
|
+
#
|
|
182
|
+
# If the key exists in the tree, returns the predecessor (previous element).
|
|
183
|
+
# If the key does not exist, returns the largest key-value pair with key < given key.
|
|
184
|
+
#
|
|
185
|
+
# @param key [Object] the reference key
|
|
186
|
+
# @return [Array(Object, Object), nil] a two-element array [key, value], or nil if no predecessor exists
|
|
187
|
+
# @example
|
|
188
|
+
# tree = RBTree.new({1 => 'one', 3 => 'three', 5 => 'five', 7 => 'seven'})
|
|
189
|
+
# tree.prev(5) # => [3, "three"]
|
|
190
|
+
# tree.prev(4) # => [3, "three"] (4 does not exist)
|
|
191
|
+
# tree.prev(1) # => nil (no predecessor)
|
|
192
|
+
def prev(key)
|
|
193
|
+
n = find_predecessor_node(key)
|
|
194
|
+
n == @nil_node ? nil : n.pair
|
|
195
|
+
end
|
|
196
|
+
|
|
197
|
+
# Returns the key-value pair with the smallest key that is larger than the given key.
|
|
198
|
+
#
|
|
199
|
+
# If the key exists in the tree, returns the successor (next element).
|
|
200
|
+
# If the key does not exist, returns the smallest key-value pair with key > given key.
|
|
201
|
+
#
|
|
202
|
+
# @param key [Object] the reference key
|
|
203
|
+
# @return [Array(Object, Object), nil] a two-element array [key, value], or nil if no successor exists
|
|
204
|
+
# @example
|
|
205
|
+
# tree = RBTree.new({1 => 'one', 3 => 'three', 5 => 'five', 7 => 'seven'})
|
|
206
|
+
# tree.succ(5) # => [7, "seven"]
|
|
207
|
+
# tree.succ(4) # => [5, "five"] (4 does not exist)
|
|
208
|
+
# tree.succ(7) # => nil (no successor)
|
|
209
|
+
def succ(key)
|
|
210
|
+
n = find_successor_node(key)
|
|
211
|
+
n == @nil_node ? nil : n.pair
|
|
212
|
+
end
|
|
213
|
+
|
|
161
214
|
# Inserts or updates a key-value pair in the tree.
|
|
162
215
|
#
|
|
163
216
|
# If the key already exists and overwrite is true (default), the value is updated.
|
|
@@ -233,17 +286,6 @@ class RBTree
|
|
|
233
286
|
value
|
|
234
287
|
end
|
|
235
288
|
|
|
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
289
|
# Removes and returns the minimum key-value pair.
|
|
248
290
|
#
|
|
249
291
|
# @return [Array(Object, Object), nil] a two-element array [key, value], or nil if tree is empty
|
|
@@ -273,6 +315,17 @@ class RBTree
|
|
|
273
315
|
result
|
|
274
316
|
end
|
|
275
317
|
|
|
318
|
+
# Removes all key-value pairs from the tree.
|
|
319
|
+
#
|
|
320
|
+
# @return [RBTree] self
|
|
321
|
+
def clear
|
|
322
|
+
@root = @nil_node
|
|
323
|
+
@min_node = @nil_node
|
|
324
|
+
@hash_index.clear
|
|
325
|
+
@size = 0
|
|
326
|
+
self
|
|
327
|
+
end
|
|
328
|
+
|
|
276
329
|
# Iterates over all key-value pairs in ascending (or descending) order.
|
|
277
330
|
#
|
|
278
331
|
# @param reverse [Boolean] if true, iterate in descending order (default: false)
|
|
@@ -296,28 +349,10 @@ class RBTree
|
|
|
296
349
|
# end
|
|
297
350
|
def each(reverse: false, safe: false, &block)
|
|
298
351
|
return enum_for(:each, reverse: reverse, safe: safe) unless block_given?
|
|
299
|
-
if
|
|
300
|
-
|
|
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
|
|
352
|
+
if reverse
|
|
353
|
+
traverse_all_desc(@root, safe: safe, &block)
|
|
315
354
|
else
|
|
316
|
-
|
|
317
|
-
traverse_desc(@root, &block)
|
|
318
|
-
else
|
|
319
|
-
traverse_asc(@root, &block)
|
|
320
|
-
end
|
|
355
|
+
traverse_all_asc(@root, safe: safe, &block)
|
|
321
356
|
end
|
|
322
357
|
self
|
|
323
358
|
end
|
|
@@ -343,22 +378,6 @@ class RBTree
|
|
|
343
378
|
# @see #each
|
|
344
379
|
def reverse_each(safe: false, &block) = each(reverse: true, safe: safe, &block)
|
|
345
380
|
|
|
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
381
|
# Retrieves all key-value pairs with keys less than the specified key.
|
|
363
382
|
#
|
|
364
383
|
# @param key [Object] the upper bound (exclusive)
|
|
@@ -373,26 +392,10 @@ class RBTree
|
|
|
373
392
|
# tree.lt(3, safe: true) { |k, _| tree.delete(k) if k.even? } # safe to delete
|
|
374
393
|
def lt(key, reverse: false, safe: false, &block)
|
|
375
394
|
return enum_for(:lt, key, reverse: reverse, safe: safe) unless block_given?
|
|
376
|
-
if
|
|
377
|
-
|
|
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)
|
|
395
|
+
if reverse
|
|
396
|
+
traverse_lt_desc(@root, key, safe: safe, &block)
|
|
394
397
|
else
|
|
395
|
-
|
|
398
|
+
traverse_lt_asc(@root, key, safe: safe, &block)
|
|
396
399
|
end
|
|
397
400
|
self
|
|
398
401
|
end
|
|
@@ -410,26 +413,10 @@ class RBTree
|
|
|
410
413
|
# tree.lte(3, reverse: true).first # => [3, "three"]
|
|
411
414
|
def lte(key, reverse: false, safe: false, &block)
|
|
412
415
|
return enum_for(:lte, key, reverse: reverse, safe: safe) unless block_given?
|
|
413
|
-
if
|
|
414
|
-
|
|
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)
|
|
416
|
+
if reverse
|
|
417
|
+
traverse_lte_desc(@root, key, safe: safe, &block)
|
|
431
418
|
else
|
|
432
|
-
|
|
419
|
+
traverse_lte_asc(@root, key, safe: safe, &block)
|
|
433
420
|
end
|
|
434
421
|
self
|
|
435
422
|
end
|
|
@@ -447,26 +434,10 @@ class RBTree
|
|
|
447
434
|
# tree.gt(2, reverse: true).first # => [4, "four"]
|
|
448
435
|
def gt(key, reverse: false, safe: false, &block)
|
|
449
436
|
return enum_for(:gt, key, reverse: reverse, safe: safe) unless block_given?
|
|
450
|
-
if
|
|
451
|
-
|
|
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)
|
|
437
|
+
if reverse
|
|
438
|
+
traverse_gt_desc(@root, key, safe: safe, &block)
|
|
468
439
|
else
|
|
469
|
-
|
|
440
|
+
traverse_gt_asc(@root, key, safe: safe, &block)
|
|
470
441
|
end
|
|
471
442
|
self
|
|
472
443
|
end
|
|
@@ -484,26 +455,10 @@ class RBTree
|
|
|
484
455
|
# tree.gte(2, reverse: true).first # => [4, "four"]
|
|
485
456
|
def gte(key, reverse: false, safe: false, &block)
|
|
486
457
|
return enum_for(:gte, key, reverse: reverse, safe: safe) unless block_given?
|
|
487
|
-
if
|
|
488
|
-
|
|
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)
|
|
458
|
+
if reverse
|
|
459
|
+
traverse_gte_desc(@root, key, safe: safe, &block)
|
|
505
460
|
else
|
|
506
|
-
|
|
461
|
+
traverse_gte_asc(@root, key, safe: safe, &block)
|
|
507
462
|
end
|
|
508
463
|
self
|
|
509
464
|
end
|
|
@@ -524,82 +479,27 @@ class RBTree
|
|
|
524
479
|
# tree.between(2, 4, reverse: true).first # => [4, "four"]
|
|
525
480
|
def between(min, max, include_min: true, include_max: true, reverse: false, safe: false, &block)
|
|
526
481
|
return enum_for(:between, min, max, include_min: include_min, include_max: include_max, reverse: reverse, safe: safe) unless block_given?
|
|
527
|
-
if
|
|
528
|
-
|
|
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)
|
|
482
|
+
if reverse
|
|
483
|
+
traverse_between_desc(@root, min, max, include_min, include_max, safe: safe, &block)
|
|
547
484
|
else
|
|
548
|
-
|
|
485
|
+
traverse_between_asc(@root, min, max, include_min, include_max, safe: safe, &block)
|
|
549
486
|
end
|
|
550
487
|
self
|
|
551
488
|
end
|
|
552
489
|
|
|
553
|
-
# Returns
|
|
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.
|
|
490
|
+
# Returns a string representation of the tree.
|
|
589
491
|
#
|
|
590
|
-
#
|
|
591
|
-
# If the key does not exist, returns the smallest key-value pair with key > given key.
|
|
492
|
+
# Shows the first 5 entries and total size. Useful for debugging.
|
|
592
493
|
#
|
|
593
|
-
# @
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
n == @nil_node ? nil : n.pair
|
|
494
|
+
# @return [String] a human-readable representation of the tree
|
|
495
|
+
def inspect
|
|
496
|
+
if @size > 0
|
|
497
|
+
content = first(5).map { |k, v| "#{k.inspect}=>#{v.inspect}" }.join(", ")
|
|
498
|
+
suffix = @size > 5 ? ", ..." : ""
|
|
499
|
+
"#<#{self.class}:0x#{object_id.to_s(16)} size=#{@size} {#{content}#{suffix}}>"
|
|
500
|
+
else
|
|
501
|
+
super
|
|
502
|
+
end
|
|
603
503
|
end
|
|
604
504
|
|
|
605
505
|
# Validates the red-black tree properties.
|
|
@@ -618,46 +518,138 @@ class RBTree
|
|
|
618
518
|
true
|
|
619
519
|
end
|
|
620
520
|
|
|
621
|
-
# @!visibility private
|
|
622
|
-
private
|
|
623
|
-
|
|
624
|
-
# Traverses the tree in ascending order (in-order traversal).
|
|
521
|
+
# @!visibility private
|
|
522
|
+
private
|
|
523
|
+
|
|
524
|
+
# Traverses the tree in ascending order (in-order traversal).
|
|
525
|
+
#
|
|
526
|
+
# @param node [Node] the current node
|
|
527
|
+
# @param min [Object] the lower bound (inclusive)
|
|
528
|
+
# @param max [Object] the upper bound (inclusive)
|
|
529
|
+
# @param include_min [Boolean] whether to include the lower bound
|
|
530
|
+
# @param include_max [Boolean] whether to include the upper bound
|
|
531
|
+
# @param safe [Boolean] whether to use safe traversal
|
|
532
|
+
# @yield [key, value] each key-value pair in ascending order
|
|
533
|
+
# @return [void]
|
|
534
|
+
def traverse_range_asc(node, min, max, include_min, include_max, safe: false, &block)
|
|
535
|
+
if safe
|
|
536
|
+
pair = !min ? find_min :
|
|
537
|
+
include_min && @hash_index[min]&.pair || find_successor(min)
|
|
538
|
+
if !max
|
|
539
|
+
while pair
|
|
540
|
+
current_key = pair[0]
|
|
541
|
+
yield pair
|
|
542
|
+
pair = find_successor(current_key)
|
|
543
|
+
end
|
|
544
|
+
else
|
|
545
|
+
while pair && pair[0] < max
|
|
546
|
+
current_key = pair[0]
|
|
547
|
+
yield pair
|
|
548
|
+
pair = find_successor(current_key)
|
|
549
|
+
end
|
|
550
|
+
end
|
|
551
|
+
yield pair if pair && max && include_max && pair[0] == max
|
|
552
|
+
else
|
|
553
|
+
stack = []
|
|
554
|
+
current = node
|
|
555
|
+
while current != @nil_node || !stack.empty?
|
|
556
|
+
while current != @nil_node
|
|
557
|
+
if min && ((current.key <=> min) < 0 ||
|
|
558
|
+
(!include_min && (current.key <=> min) == 0))
|
|
559
|
+
current = current.right
|
|
560
|
+
else
|
|
561
|
+
stack << current
|
|
562
|
+
current = current.left
|
|
563
|
+
end
|
|
564
|
+
end
|
|
565
|
+
|
|
566
|
+
if !stack.empty?
|
|
567
|
+
current = stack.pop
|
|
568
|
+
|
|
569
|
+
if max && ((current.key <=> max) > 0 ||
|
|
570
|
+
(!include_max && (current.key <=> max) == 0))
|
|
571
|
+
return
|
|
572
|
+
else
|
|
573
|
+
yield current.pair
|
|
574
|
+
current = current.right
|
|
575
|
+
end
|
|
576
|
+
end
|
|
577
|
+
end
|
|
578
|
+
end
|
|
579
|
+
end
|
|
580
|
+
|
|
581
|
+
# Traverses the tree in descending order (reverse in-order traversal).
|
|
625
582
|
#
|
|
626
583
|
# @param node [Node] the current node
|
|
627
|
-
# @
|
|
584
|
+
# @param min [Object] the lower bound (inclusive)
|
|
585
|
+
# @param max [Object] the upper bound (inclusive)
|
|
586
|
+
# @param include_min [Boolean] whether to include the lower bound
|
|
587
|
+
# @param include_max [Boolean] whether to include the upper bound
|
|
588
|
+
# @param safe [Boolean] whether to use safe traversal
|
|
589
|
+
# @yield [key, value] each key-value pair in descending order
|
|
628
590
|
# @return [void]
|
|
629
|
-
def
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
591
|
+
def traverse_range_desc(node, min, max, include_min, include_max, safe: false, &block)
|
|
592
|
+
if safe
|
|
593
|
+
pair = !max ? find_max :
|
|
594
|
+
include_max && @hash_index[max]&.pair || find_predecessor(max)
|
|
595
|
+
if !min
|
|
596
|
+
while pair
|
|
597
|
+
current_key = pair[0]
|
|
598
|
+
yield pair
|
|
599
|
+
pair = find_predecessor(current_key)
|
|
600
|
+
end
|
|
601
|
+
else
|
|
602
|
+
while pair && pair[0] > min
|
|
603
|
+
current_key = pair[0]
|
|
604
|
+
yield pair
|
|
605
|
+
pair = find_predecessor(current_key)
|
|
606
|
+
end
|
|
607
|
+
end
|
|
608
|
+
yield pair if pair && min && include_min && pair[0] == min
|
|
609
|
+
else
|
|
610
|
+
stack = []
|
|
611
|
+
current = node
|
|
612
|
+
while current != @nil_node || !stack.empty?
|
|
613
|
+
while current != @nil_node
|
|
614
|
+
if max && ((current.key <=> max) > 0 ||
|
|
615
|
+
(!include_max && (current.key <=> max) == 0))
|
|
616
|
+
current = current.left
|
|
617
|
+
else
|
|
618
|
+
stack << current
|
|
619
|
+
current = current.right
|
|
620
|
+
end
|
|
621
|
+
end
|
|
622
|
+
|
|
623
|
+
if !stack.empty?
|
|
624
|
+
current = stack.pop
|
|
625
|
+
|
|
626
|
+
if min && ((current.key <=> min) < 0 ||
|
|
627
|
+
(!include_min && (current.key <=> min) == 0))
|
|
628
|
+
return
|
|
629
|
+
else
|
|
630
|
+
yield current.pair
|
|
631
|
+
current = current.left
|
|
632
|
+
end
|
|
633
|
+
end
|
|
636
634
|
end
|
|
637
|
-
current = stack.pop
|
|
638
|
-
yield current.pair
|
|
639
|
-
current = current.right
|
|
640
635
|
end
|
|
641
636
|
end
|
|
642
637
|
|
|
638
|
+
# Traverses the tree in ascending order (in-order traversal).
|
|
639
|
+
#
|
|
640
|
+
# @param node [Node] the current node
|
|
641
|
+
# @yield [key, value] each key-value pair in ascending order
|
|
642
|
+
# @return [void]
|
|
643
|
+
def traverse_all_asc(node, safe: false, &block) =
|
|
644
|
+
traverse_range_asc(node, nil, nil, false, false, safe: safe, &block)
|
|
645
|
+
|
|
643
646
|
# Traverses the tree in descending order (reverse in-order traversal).
|
|
644
647
|
#
|
|
645
648
|
# @param node [Node] the current node
|
|
646
649
|
# @yield [key, value] each key-value pair in descending order
|
|
647
650
|
# @return [void]
|
|
648
|
-
def
|
|
649
|
-
|
|
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
|
|
651
|
+
def traverse_all_desc(node, safe: false, &block) =
|
|
652
|
+
traverse_range_desc(node, nil, nil, false, false, safe: safe, &block)
|
|
661
653
|
|
|
662
654
|
# Traverses nodes with keys less than the specified key.
|
|
663
655
|
#
|
|
@@ -665,15 +657,8 @@ class RBTree
|
|
|
665
657
|
# @param key [Object] the upper bound (exclusive)
|
|
666
658
|
# @yield [key, value] each matching key-value pair
|
|
667
659
|
# @return [void]
|
|
668
|
-
def
|
|
669
|
-
|
|
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
|
|
660
|
+
def traverse_lt_asc(node, key, safe: false, &block) =
|
|
661
|
+
traverse_range_asc(node, nil, key, false, false, safe: safe, &block)
|
|
677
662
|
|
|
678
663
|
# Traverses nodes with keys less than or equal to the specified key.
|
|
679
664
|
#
|
|
@@ -681,15 +666,8 @@ class RBTree
|
|
|
681
666
|
# @param key [Object] the upper bound (inclusive)
|
|
682
667
|
# @yield [key, value] each matching key-value pair
|
|
683
668
|
# @return [void]
|
|
684
|
-
def
|
|
685
|
-
|
|
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
|
|
669
|
+
def traverse_lte_asc(node, key, safe: false, &block) =
|
|
670
|
+
traverse_range_asc(node, nil, key, false, true, safe: safe, &block)
|
|
693
671
|
|
|
694
672
|
# Traverses nodes with keys greater than the specified key.
|
|
695
673
|
#
|
|
@@ -697,15 +675,8 @@ class RBTree
|
|
|
697
675
|
# @param key [Object] the lower bound (exclusive)
|
|
698
676
|
# @yield [key, value] each matching key-value pair
|
|
699
677
|
# @return [void]
|
|
700
|
-
def
|
|
701
|
-
|
|
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
|
|
678
|
+
def traverse_gt_asc(node, key, safe: false, &block) =
|
|
679
|
+
traverse_range_asc(node, key, nil, false, false, safe: safe, &block)
|
|
709
680
|
|
|
710
681
|
# Traverses nodes with keys greater than or equal to the specified key.
|
|
711
682
|
#
|
|
@@ -713,15 +684,8 @@ class RBTree
|
|
|
713
684
|
# @param key [Object] the lower bound (inclusive)
|
|
714
685
|
# @yield [key, value] each matching key-value pair
|
|
715
686
|
# @return [void]
|
|
716
|
-
def
|
|
717
|
-
|
|
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
|
|
687
|
+
def traverse_gte_asc(node, key, safe: false, &block) =
|
|
688
|
+
traverse_range_asc(node, key, nil, true, false, safe: safe, &block)
|
|
725
689
|
|
|
726
690
|
# Traverses nodes with keys within the specified range.
|
|
727
691
|
#
|
|
@@ -732,23 +696,8 @@ class RBTree
|
|
|
732
696
|
# @param include_max [Boolean] whether to include the upper bound
|
|
733
697
|
# @yield [key, value] each matching key-value pair
|
|
734
698
|
# @return [void]
|
|
735
|
-
def
|
|
736
|
-
|
|
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
|
|
699
|
+
def traverse_between_asc(node, min, max, include_min, include_max, safe: false, &block) =
|
|
700
|
+
traverse_range_asc(node, min, max, include_min, include_max, safe: safe, &block)
|
|
752
701
|
|
|
753
702
|
# Traverses nodes with keys less than the specified key in descending order.
|
|
754
703
|
#
|
|
@@ -756,15 +705,8 @@ class RBTree
|
|
|
756
705
|
# @param key [Object] the upper bound (exclusive)
|
|
757
706
|
# @yield [key, value] each matching key-value pair in descending order
|
|
758
707
|
# @return [void]
|
|
759
|
-
def traverse_lt_desc(node, key, &block)
|
|
760
|
-
|
|
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
|
|
708
|
+
def traverse_lt_desc(node, key, safe: false, &block) =
|
|
709
|
+
traverse_range_desc(node, nil, key, false, false, safe: safe, &block)
|
|
768
710
|
|
|
769
711
|
# Traverses nodes with keys less than or equal to the specified key in descending order.
|
|
770
712
|
#
|
|
@@ -772,15 +714,8 @@ class RBTree
|
|
|
772
714
|
# @param key [Object] the upper bound (inclusive)
|
|
773
715
|
# @yield [key, value] each matching key-value pair in descending order
|
|
774
716
|
# @return [void]
|
|
775
|
-
def traverse_lte_desc(node, key, &block)
|
|
776
|
-
|
|
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
|
|
717
|
+
def traverse_lte_desc(node, key, safe: false, &block) =
|
|
718
|
+
traverse_range_desc(node, nil, key, false, true, safe: safe, &block)
|
|
784
719
|
|
|
785
720
|
# Traverses nodes with keys greater than the specified key in descending order.
|
|
786
721
|
#
|
|
@@ -788,15 +723,8 @@ class RBTree
|
|
|
788
723
|
# @param key [Object] the lower bound (exclusive)
|
|
789
724
|
# @yield [key, value] each matching key-value pair in descending order
|
|
790
725
|
# @return [void]
|
|
791
|
-
def traverse_gt_desc(node, key, &block)
|
|
792
|
-
|
|
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
|
|
726
|
+
def traverse_gt_desc(node, key, safe: false, &block) =
|
|
727
|
+
traverse_range_desc(node, key, nil, false, false, safe: safe, &block)
|
|
800
728
|
|
|
801
729
|
# Traverses nodes with keys greater than or equal to the specified key in descending order.
|
|
802
730
|
#
|
|
@@ -804,15 +732,8 @@ class RBTree
|
|
|
804
732
|
# @param key [Object] the lower bound (inclusive)
|
|
805
733
|
# @yield [key, value] each matching key-value pair in descending order
|
|
806
734
|
# @return [void]
|
|
807
|
-
def traverse_gte_desc(node, key, &block)
|
|
808
|
-
|
|
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
|
|
735
|
+
def traverse_gte_desc(node, key, safe: false, &block) =
|
|
736
|
+
traverse_range_desc(node, key, nil, true, false, safe: safe, &block)
|
|
816
737
|
|
|
817
738
|
# Traverses nodes with keys within the specified range in descending order.
|
|
818
739
|
#
|
|
@@ -823,24 +744,8 @@ class RBTree
|
|
|
823
744
|
# @param include_max [Boolean] whether to include the upper bound
|
|
824
745
|
# @yield [key, value] each matching key-value pair in descending order
|
|
825
746
|
# @return [void]
|
|
826
|
-
def traverse_between_desc(node, min, max, include_min, include_max, &block)
|
|
827
|
-
|
|
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
|
|
747
|
+
def traverse_between_desc(node, min, max, include_min, include_max, safe: false, &block) =
|
|
748
|
+
traverse_range_desc(node, min, max, include_min, include_max, safe: safe, &block)
|
|
844
749
|
|
|
845
750
|
# Restores red-black tree properties after insertion.
|
|
846
751
|
#
|
|
@@ -1407,6 +1312,17 @@ end
|
|
|
1407
1312
|
# @author Masahito Suzuki
|
|
1408
1313
|
# @since 0.1.2
|
|
1409
1314
|
class MultiRBTree < RBTree
|
|
1315
|
+
def min(last: false)
|
|
1316
|
+
return nil if @min_node == @nil_node || @min_node.value.empty?
|
|
1317
|
+
[@min_node.key, last ? @min_node.value.last : @min_node.value.first]
|
|
1318
|
+
end
|
|
1319
|
+
|
|
1320
|
+
def max(last: false)
|
|
1321
|
+
n = rightmost(@root)
|
|
1322
|
+
return nil if n == @nil_node || n.value.empty?
|
|
1323
|
+
[n.key, last ? n.value.last : n.value.first]
|
|
1324
|
+
end
|
|
1325
|
+
|
|
1410
1326
|
# Retrieves a value associated with the given key.
|
|
1411
1327
|
#
|
|
1412
1328
|
# @param key [Object] the key to look up
|
|
@@ -1436,26 +1352,22 @@ class MultiRBTree < RBTree
|
|
|
1436
1352
|
# @return [Object, nil] the last value for the key, or nil if not found
|
|
1437
1353
|
def get_last(key) = get(key, last: true)
|
|
1438
1354
|
|
|
1439
|
-
|
|
1440
|
-
|
|
1441
|
-
|
|
1442
|
-
|
|
1443
|
-
|
|
1444
|
-
# @return [Object, nil] the first value for the key, or nil if not found
|
|
1445
|
-
def [](key) = get(key)
|
|
1355
|
+
def nearest(key, last: false)
|
|
1356
|
+
n = find_nearest_node(key)
|
|
1357
|
+
return nil if n == @nil_node || n.value.empty?
|
|
1358
|
+
[n.key, last ? n.value.last : n.value.first]
|
|
1359
|
+
end
|
|
1446
1360
|
|
|
1447
|
-
|
|
1448
|
-
|
|
1449
|
-
|
|
1450
|
-
|
|
1451
|
-
|
|
1452
|
-
|
|
1453
|
-
|
|
1454
|
-
|
|
1455
|
-
|
|
1456
|
-
|
|
1457
|
-
return enum_for(:get_all, key) unless block_given?
|
|
1458
|
-
@hash_index[key]&.value&.each { |v| yield v }
|
|
1361
|
+
def prev(key, last: false)
|
|
1362
|
+
pair = super(key)
|
|
1363
|
+
return nil unless pair
|
|
1364
|
+
[pair[0], last ? pair[1].last : pair[1].first]
|
|
1365
|
+
end
|
|
1366
|
+
|
|
1367
|
+
def succ(key, last: false)
|
|
1368
|
+
pair = super(key)
|
|
1369
|
+
return nil unless pair
|
|
1370
|
+
[pair[0], last ? pair[1].last : pair[1].first]
|
|
1459
1371
|
end
|
|
1460
1372
|
|
|
1461
1373
|
# Inserts a value for the given key.
|
|
@@ -1583,7 +1495,7 @@ class MultiRBTree < RBTree
|
|
|
1583
1495
|
node.value.shift
|
|
1584
1496
|
@size -= 1
|
|
1585
1497
|
if node.value.empty?
|
|
1586
|
-
|
|
1498
|
+
delete_node(key)
|
|
1587
1499
|
end
|
|
1588
1500
|
[key, val]
|
|
1589
1501
|
end
|
|
@@ -1591,246 +1503,38 @@ class MultiRBTree < RBTree
|
|
|
1591
1503
|
def pop
|
|
1592
1504
|
n = rightmost(@root)
|
|
1593
1505
|
return nil if n == @nil_node
|
|
1506
|
+
key = n.key
|
|
1594
1507
|
val = n.value.last
|
|
1595
1508
|
n.value.pop
|
|
1596
1509
|
@size -= 1
|
|
1597
1510
|
if n.value.empty?
|
|
1598
|
-
|
|
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
|
|
1511
|
+
delete_node(key)
|
|
1672
1512
|
end
|
|
1513
|
+
[key, val]
|
|
1673
1514
|
end
|
|
1674
1515
|
|
|
1675
|
-
|
|
1676
|
-
|
|
1677
|
-
|
|
1678
|
-
|
|
1679
|
-
|
|
1680
|
-
|
|
1681
|
-
|
|
1682
|
-
|
|
1683
|
-
|
|
1516
|
+
# Retrieves all values associated with the given key.
|
|
1517
|
+
#
|
|
1518
|
+
# @param key [Object] the key to look up
|
|
1519
|
+
# @return [Array, nil] an Array containing all values, or nil if not found
|
|
1520
|
+
# @example
|
|
1521
|
+
# tree = MultiRBTree.new
|
|
1522
|
+
# tree.insert(1, 'first')
|
|
1523
|
+
# tree.insert(1, 'second')
|
|
1524
|
+
# tree.get_all(1).to_a # => ["first", "second"]
|
|
1525
|
+
def get_all(key)
|
|
1526
|
+
return enum_for(:get_all, key) unless block_given?
|
|
1527
|
+
@hash_index[key]&.value&.each { |v| yield v }
|
|
1684
1528
|
end
|
|
1685
1529
|
|
|
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
1530
|
private
|
|
1690
1531
|
|
|
1691
|
-
def
|
|
1692
|
-
|
|
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 }
|
|
1783
|
-
end
|
|
1784
|
-
traverse_lt_desc(node.left, key, &block)
|
|
1785
|
-
end
|
|
1786
|
-
|
|
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)
|
|
1795
|
-
end
|
|
1796
|
-
|
|
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
|
|
1806
|
-
|
|
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
|
|
1532
|
+
def traverse_range_asc(...)
|
|
1533
|
+
super { |k, vals| vals.each { |v| yield k, v } }
|
|
1815
1534
|
end
|
|
1816
1535
|
|
|
1817
|
-
def
|
|
1818
|
-
|
|
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
|
|
1536
|
+
def traverse_range_desc(...)
|
|
1537
|
+
super { |k, vals| vals.reverse_each { |v| yield k, v } }
|
|
1834
1538
|
end
|
|
1835
1539
|
end
|
|
1836
1540
|
|
|
@@ -1878,14 +1582,6 @@ class RBTree::Node
|
|
|
1878
1582
|
@parent = parent
|
|
1879
1583
|
end
|
|
1880
1584
|
|
|
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
1585
|
# Returns the key-value pair.
|
|
1890
1586
|
# @return [Array(Object, Object)] the key-value pair
|
|
1891
1587
|
def pair = [key, value]
|