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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +23 -0
- data/README.ja.md +12 -6
- data/README.md +8 -4
- data/lib/rbtree/version.rb +1 -1
- data/lib/rbtree.rb +411 -664
- metadata +1 -1
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
|
|
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
|
-
|
|
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.
|
|
100
|
-
|
|
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
|
-
#
|
|
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
|
|
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
|
-
# @
|
|
170
|
-
# @
|
|
171
|
-
#
|
|
172
|
-
# tree.insert(1, 'one')
|
|
173
|
-
#
|
|
174
|
-
# tree.insert(1
|
|
175
|
-
#
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
return
|
|
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
|
-
|
|
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
|
|
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
|
|
351
|
+
if reverse
|
|
352
|
+
traverse_all_desc(@root, safe: safe, &block)
|
|
315
353
|
else
|
|
316
|
-
|
|
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
|
|
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)
|
|
394
|
+
if reverse
|
|
395
|
+
traverse_lt_desc(@root, key, safe: safe, &block)
|
|
394
396
|
else
|
|
395
|
-
|
|
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
|
|
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)
|
|
415
|
+
if reverse
|
|
416
|
+
traverse_lte_desc(@root, key, safe: safe, &block)
|
|
431
417
|
else
|
|
432
|
-
|
|
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
|
|
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)
|
|
436
|
+
if reverse
|
|
437
|
+
traverse_gt_desc(@root, key, safe: safe, &block)
|
|
468
438
|
else
|
|
469
|
-
|
|
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
|
|
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)
|
|
457
|
+
if reverse
|
|
458
|
+
traverse_gte_desc(@root, key, safe: safe, &block)
|
|
505
459
|
else
|
|
506
|
-
|
|
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
|
|
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)
|
|
481
|
+
if reverse
|
|
482
|
+
traverse_between_desc(@root, min, max, include_min, include_max, safe: safe, &block)
|
|
547
483
|
else
|
|
548
|
-
|
|
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
|
|
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
|
-
#
|
|
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
|
-
# @
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
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
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
#
|
|
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
|
-
# @
|
|
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
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
1440
|
-
|
|
1441
|
-
|
|
1442
|
-
|
|
1443
|
-
|
|
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
|
-
|
|
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 }
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
1563
|
+
[key, val]
|
|
1785
1564
|
end
|
|
1786
1565
|
|
|
1787
|
-
|
|
1788
|
-
|
|
1789
|
-
|
|
1790
|
-
|
|
1791
|
-
|
|
1792
|
-
|
|
1793
|
-
|
|
1794
|
-
|
|
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
|
-
|
|
1798
|
-
|
|
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
|
|
1808
|
-
|
|
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
|
|
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
|
|
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]
|