rbtree-ruby 0.1.0 → 0.1.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.
data/lib/rbtree.rb ADDED
@@ -0,0 +1,1260 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "rbtree/version"
4
+
5
+ # A Red-Black Tree implementation providing efficient ordered key-value storage.
6
+ #
7
+ # RBTree is a self-balancing binary search tree that maintains sorted order of keys
8
+ # and provides O(log n) time complexity for insertion, deletion, and lookup operations.
9
+ # The tree enforces the following red-black properties to maintain balance:
10
+ #
11
+ # 1. Every node is either red or black
12
+ # 2. The root is always black
13
+ # 3. All leaves (nil nodes) are black
14
+ # 4. Red nodes cannot have red children
15
+ # 5. All paths from root to leaves contain the same number of black nodes
16
+ #
17
+ # == Features
18
+ #
19
+ # * Ordered iteration over key-value pairs
20
+ # * Range queries (less than, greater than, between)
21
+ # * Efficient min/max retrieval
22
+ # * Nearest key search for numeric keys
23
+ # * Tree integrity validation
24
+ #
25
+ # == Usage
26
+ #
27
+ # # Create an empty tree
28
+ # tree = RBTree.new
29
+ #
30
+ # # Create from a hash
31
+ # tree = RBTree.new({3 => 'three', 1 => 'one', 2 => 'two'})
32
+ #
33
+ # # Create from an array of key-value pairs
34
+ # tree = RBTree.new([[3, 'three'], [1, 'one'], [2, 'two']])
35
+ #
36
+ # # Create using bracket notation
37
+ # tree = RBTree[3 => 'three', 1 => 'one', 2 => 'two']
38
+ #
39
+ # # Insert and retrieve values
40
+ # tree.insert(5, 'five')
41
+ # tree[4] = 'four'
42
+ # puts tree[4] # => "four"
43
+ #
44
+ # # Iterate in sorted order
45
+ # tree.each { |key, value| puts "#{key}: #{value}" }
46
+ #
47
+ # == Performance
48
+ #
49
+ # All major operations (insert, delete, search) run in O(log n) time.
50
+ # Iteration over all elements takes O(n) time.
51
+ #
52
+ # @author Masahito Suzuki
53
+ # @since 0.1.0
54
+ class RBTree
55
+ include Enumerable
56
+
57
+ # Returns the number of key-value pairs stored in the tree.
58
+ # @return [Integer] the number of entries in the tree
59
+ attr_reader :size
60
+
61
+ # Creates a new RBTree from the given arguments.
62
+ #
63
+ # This is a convenience method equivalent to RBTree.new(*args).
64
+ #
65
+ # @param args [Hash, Array] optional initial data
66
+ # @return [RBTree] a new RBTree instance
67
+ # @example
68
+ # tree = RBTree[1 => 'one', 2 => 'two', 3 => 'three']
69
+ def self.[](*args)
70
+ new(*args)
71
+ end
72
+
73
+ # Initializes a new RBTree.
74
+ #
75
+ # The tree can be initialized empty or populated with initial data from a Hash or Array.
76
+ #
77
+ # @param args [Hash, Array, nil] optional initial data
78
+ # - If a Hash is provided, each key-value pair is inserted into the tree
79
+ # - If an Array is provided, it should contain [key, value] pairs
80
+ # - If no arguments are provided, an empty tree is created
81
+ # @raise [ArgumentError] if arguments are invalid
82
+ # @example Create an empty tree
83
+ # tree = RBTree.new
84
+ # @example Create from a hash
85
+ # tree = RBTree.new({1 => 'one', 2 => 'two'})
86
+ # @example Create from an array
87
+ # tree = RBTree.new([[1, 'one'], [2, 'two']])
88
+ def initialize(*args)
89
+ @nil_node = Node.new
90
+ @nil_node.color = Node::BLACK
91
+ @nil_node.left = @nil_node
92
+ @nil_node.right = @nil_node
93
+ @root = @nil_node
94
+ @min_node = @nil_node
95
+ @size = 0
96
+
97
+ if args.any?
98
+ source = args.size == 1 ? args.first : args
99
+ case source
100
+ when Hash
101
+ source.each { |k, v| insert(k, v) }
102
+ when Array
103
+ source.each do |arg|
104
+ key, value = arg
105
+ insert(key, value)
106
+ end
107
+ else
108
+ raise ArgumentError, "Invalid arguments"
109
+ end
110
+ end
111
+ end
112
+
113
+ # Returns a string representation of the tree.
114
+ #
115
+ # Shows the first 5 entries and total size. Useful for debugging.
116
+ #
117
+ # @return [String] a human-readable representation of the tree
118
+ def inspect
119
+ if @size > 0
120
+ content = first(5).map { |k, v| "#{k.inspect}=>#{v.inspect}" }.join(", ")
121
+ suffix = @size > 5 ? ", ..." : ""
122
+ "#<#{self.class}:0x#{object_id.to_s(16)} size=#{@size} {#{content}#{suffix}}>"
123
+ else
124
+ super
125
+ end
126
+ end
127
+
128
+ # Checks if the tree is empty.
129
+ #
130
+ # @return [Boolean] true if the tree contains no elements, false otherwise
131
+ def empty? = @root == @nil_node
132
+
133
+ # Checks if the tree contains the given key.
134
+ #
135
+ # @param key [Object] the key to search for
136
+ # @return [Boolean] true if the key exists in the tree, false otherwise
137
+ # @example
138
+ # tree = RBTree.new({1 => 'one', 2 => 'two'})
139
+ # tree.has_key?(1) # => true
140
+ # tree.has_key?(3) # => false
141
+ def has_key?(key)
142
+ find_node(key) != @nil_node
143
+ end
144
+
145
+ # Retrieves the value associated with the given key.
146
+ #
147
+ # @param key [Object] the key to look up
148
+ # @return [Object, nil] the associated value, or nil if the key is not found
149
+ # @example
150
+ # tree = RBTree.new({1 => 'one', 2 => 'two'})
151
+ # tree.get(1) # => "one"
152
+ # tree[2] # => "two"
153
+ # tree[3] # => nil
154
+ def get(key)
155
+ n = find_node(key)
156
+ n == @nil_node ? nil : n.value
157
+ end
158
+ alias_method :[], :get
159
+
160
+ # Inserts or updates a key-value pair in the tree.
161
+ #
162
+ # If the key already exists and overwrite is true (default), the value is updated.
163
+ # If overwrite is false and the key exists, the operation returns nil without modification.
164
+ #
165
+ # @param key [Object] the key to insert (must implement <=>)
166
+ # @param value [Object] the value to associate with the key
167
+ # @param overwrite [Boolean] whether to overwrite existing keys (default: true)
168
+ # @return [Boolean, nil] true if inserted/updated, nil if key exists and overwrite is false
169
+ # @example
170
+ # tree = RBTree.new
171
+ # tree.insert(1, 'one') # => true
172
+ # tree.insert(1, 'ONE') # => true (overwrites)
173
+ # tree.insert(1, 'uno', overwrite: false) # => nil (no change)
174
+ # tree[2] = 'two' # using alias
175
+ def insert(key, value, overwrite: true)
176
+ y = @nil_node
177
+ x = @root
178
+ while x != @nil_node
179
+ y = x
180
+ cmp = key <=> x.key
181
+ if cmp == 0
182
+ return nil unless overwrite
183
+ x.value = value
184
+ return true
185
+ elsif cmp < 0
186
+ x = x.left
187
+ else
188
+ x = x.right
189
+ end
190
+ end
191
+ z = Node.new(key, value, Node::RED, @nil_node, @nil_node, @nil_node)
192
+ z.parent = y
193
+ if y == @nil_node
194
+ @root = z
195
+ elsif (key <=> y.key) < 0
196
+ y.left = z
197
+ else
198
+ y.right = z
199
+ end
200
+ z.left = @nil_node
201
+ z.right = @nil_node
202
+ z.color = Node::RED
203
+ insert_fixup(z)
204
+ @size += 1
205
+
206
+ if @min_node == @nil_node || (key <=> @min_node.key) < 0
207
+ @min_node = z
208
+ end
209
+
210
+ true
211
+ end
212
+ alias_method :[]=, :insert
213
+
214
+ # Deletes the key-value pair with the specified key.
215
+ #
216
+ # @param key [Object] the key to delete
217
+ # @return [Object, nil] the value associated with the deleted key, or nil if not found
218
+ # @example
219
+ # tree = RBTree.new({1 => 'one', 2 => 'two'})
220
+ # tree.delete(1) # => "one"
221
+ # tree.delete(3) # => nil
222
+ def delete(key)
223
+ value = delete_node(key)
224
+ return nil unless value
225
+ @size -= 1
226
+ value
227
+ end
228
+
229
+ # Removes all key-value pairs from the tree.
230
+ #
231
+ # @return [RBTree] self
232
+ def clear
233
+ @root = @nil_node
234
+ @min_node = @nil_node
235
+ @size = 0
236
+ self
237
+ end
238
+
239
+ # Removes and returns the minimum key-value pair.
240
+ #
241
+ # @return [Array(Object, Object), nil] a two-element array [key, value], or nil if tree is empty
242
+ # @example
243
+ # tree = RBTree.new({3 => 'three', 1 => 'one', 2 => 'two'})
244
+ # tree.shift # => [1, "one"]
245
+ # tree.shift # => [2, "two"]
246
+ def shift
247
+ return nil if @min_node == @nil_node
248
+ result = [@min_node.key, @min_node.value]
249
+ delete(@min_node.key)
250
+ result
251
+ end
252
+
253
+ # Removes and returns the maximum key-value pair.
254
+ #
255
+ # @return [Array(Object, Object), nil] a two-element array [key, value], or nil if tree is empty
256
+ # @example
257
+ # tree = RBTree.new({3 => 'three', 1 => 'one', 2 => 'two'})
258
+ # tree.pop # => [3, "three"]
259
+ # tree.pop # => [2, "two"]
260
+ def pop
261
+ n = rightmost(@root)
262
+ return nil if n == @nil_node
263
+ result = [n.key, n.value]
264
+ delete(n.key)
265
+ result
266
+ end
267
+
268
+ # Iterates over all key-value pairs in ascending order of keys.
269
+ #
270
+ # @yield [key, value] each key-value pair in the tree
271
+ # @return [Enumerator, RBTree] an Enumerator if no block is given, self otherwise
272
+ # @example
273
+ # tree = RBTree.new({3 => 'three', 1 => 'one', 2 => 'two'})
274
+ # tree.each { |k, v| puts "#{k}: #{v}" }
275
+ # # Output:
276
+ # # 1: one
277
+ # # 2: two
278
+ # # 3: three
279
+ def each(&block)
280
+ return enum_for(:each) unless block_given?
281
+ traverse_asc(@root, &block)
282
+ end
283
+
284
+ # Iterates over all key-value pairs in descending order of keys.
285
+ #
286
+ # @yield [key, value] each key-value pair in the tree
287
+ # @return [Enumerator, RBTree] an Enumerator if no block is given, self otherwise
288
+ # @example
289
+ # tree = RBTree.new({3 => 'three', 1 => 'one', 2 => 'two'})
290
+ # tree.reverse_each { |k, v| puts "#{k}: #{v}" }
291
+ # # Output:
292
+ # # 3: three
293
+ # # 2: two
294
+ # # 1: one
295
+ def reverse_each(&block)
296
+ return enum_for(:reverse_each) unless block_given?
297
+ traverse_desc(@root, &block)
298
+ end
299
+
300
+ # Returns the minimum key-value pair without removing it.
301
+ #
302
+ # @return [Array(Object, Object), nil] a two-element array [key, value], or nil if tree is empty
303
+ # @example
304
+ # tree = RBTree.new({3 => 'three', 1 => 'one', 2 => 'two'})
305
+ # tree.min # => [1, "one"]
306
+ def min
307
+ @min_node == @nil_node ? nil : [@min_node.key, @min_node.value]
308
+ end
309
+
310
+ # Returns the maximum key-value pair without removing it.
311
+ #
312
+ # @return [Array(Object, Object), nil] a two-element array [key, value], or nil if tree is empty
313
+ # @example
314
+ # tree = RBTree.new({3 => 'three', 1 => 'one', 2 => 'two'})
315
+ # tree.max # => [3, "three"]
316
+ def max
317
+ n = rightmost(@root)
318
+ n == @nil_node ? nil : [n.key, n.value]
319
+ end
320
+
321
+ # Retrieves all key-value pairs with keys less than the specified key.
322
+ #
323
+ # @param key [Object] the upper bound (exclusive)
324
+ # @yield [key, value] each matching key-value pair (if block given)
325
+ # @return [Array<Array(Object, Object)>, RBTree] array of [key, value] pairs if no block, self otherwise
326
+ # @example
327
+ # tree = RBTree.new({1 => 'one', 2 => 'two', 3 => 'three', 4 => 'four'})
328
+ # tree.lt(3) # => [[1, "one"], [2, "two"]]
329
+ # tree.lt(3) { |k, v| puts "#{k}: #{v}" } # prints pairs and returns tree
330
+ def lt(key, &block)
331
+ if block_given?
332
+ traverse_lt(@root, key, &block)
333
+ self
334
+ else
335
+ res = []
336
+ traverse_lt(@root, key) { |k, v| res << [k, v] }
337
+ res
338
+ end
339
+ end
340
+
341
+ # Retrieves all key-value pairs with keys less than or equal to the specified key.
342
+ #
343
+ # @param key [Object] the upper bound (inclusive)
344
+ # @yield [key, value] each matching key-value pair (if block given)
345
+ # @return [Array<Array(Object, Object)>, RBTree] array of [key, value] pairs if no block, self otherwise
346
+ # @example
347
+ # tree = RBTree.new({1 => 'one', 2 => 'two', 3 => 'three', 4 => 'four'})
348
+ # tree.lte(3) # => [[1, "one"], [2, "two"], [3, "three"]]
349
+ def lte(key, &block)
350
+ if block_given?
351
+ traverse_lte(@root, key, &block)
352
+ self
353
+ else
354
+ res = []
355
+ traverse_lte(@root, key) { |k, v| res << [k, v] }
356
+ res
357
+ end
358
+ end
359
+
360
+ # Retrieves all key-value pairs with keys greater than the specified key.
361
+ #
362
+ # @param key [Object] the lower bound (exclusive)
363
+ # @yield [key, value] each matching key-value pair (if block given)
364
+ # @return [Array<Array(Object, Object)>, RBTree] array of [key, value] pairs if no block, self otherwise
365
+ # @example
366
+ # tree = RBTree.new({1 => 'one', 2 => 'two', 3 => 'three', 4 => 'four'})
367
+ # tree.gt(2) # => [[3, "three"], [4, "four"]]
368
+ def gt(key, &block)
369
+ if block_given?
370
+ traverse_gt(@root, key, &block)
371
+ self
372
+ else
373
+ res = []
374
+ traverse_gt(@root, key) { |k, v| res << [k, v] }
375
+ res
376
+ end
377
+ end
378
+
379
+ # Retrieves all key-value pairs with keys greater than or equal to the specified key.
380
+ #
381
+ # @param key [Object] the lower bound (inclusive)
382
+ # @yield [key, value] each matching key-value pair (if block given)
383
+ # @return [Array<Array(Object, Object)>, RBTree] array of [key, value] pairs if no block, self otherwise
384
+ # @example
385
+ # tree = RBTree.new({1 => 'one', 2 => 'two', 3 => 'three', 4 => 'four'})
386
+ # tree.gte(2) # => [[2, "two"], [3, "three"], [4, "four"]]
387
+ def gte(key, &block)
388
+ if block_given?
389
+ traverse_gte(@root, key, &block)
390
+ self
391
+ else
392
+ res = []
393
+ traverse_gte(@root, key) { |k, v| res << [k, v] }
394
+ res
395
+ end
396
+ end
397
+
398
+ # Retrieves all key-value pairs with keys within the specified range.
399
+ #
400
+ # @param min [Object] the lower bound
401
+ # @param max [Object] the upper bound
402
+ # @param include_min [Boolean] whether to include the lower bound (default: true)
403
+ # @param include_max [Boolean] whether to include the upper bound (default: true)
404
+ # @yield [key, value] each matching key-value pair (if block given)
405
+ # @return [Array<Array(Object, Object)>, RBTree] array of [key, value] pairs if no block, self otherwise
406
+ # @example
407
+ # tree = RBTree.new({1 => 'one', 2 => 'two', 3 => 'three', 4 => 'four', 5 => 'five'})
408
+ # tree.between(2, 4) # => [[2, "two"], [3, "three"], [4, "four"]]
409
+ # tree.between(2, 4, include_min: false) # => [[3, "three"], [4, "four"]]
410
+ # tree.between(2, 4, include_max: false) # => [[2, "two"], [3, "three"]]
411
+ def between(min, max, include_min: true, include_max: true, &block)
412
+ if block_given?
413
+ traverse_between(@root, min, max, include_min, include_max, &block)
414
+ self
415
+ else
416
+ res = []
417
+ traverse_between(@root, min, max, include_min, include_max) { |k, v| res << [k, v] }
418
+ res
419
+ end
420
+ end
421
+
422
+ # Returns the key-value pair with the key closest to the given key.
423
+ #
424
+ # This method requires keys to be numeric or support subtraction and abs methods.
425
+ # If multiple keys have the same distance, the one with the smaller key is returned.
426
+ #
427
+ # @param key [Numeric] the target key
428
+ # @return [Array(Object, Object), nil] a two-element array [key, value], or nil if tree is empty
429
+ # @example
430
+ # tree = RBTree.new({1 => 'one', 5 => 'five', 10 => 'ten'})
431
+ # tree.nearest(4) # => [5, "five"]
432
+ # tree.nearest(7) # => [5, "five"]
433
+ # tree.nearest(8) # => [10, "ten"]
434
+ def nearest(key)
435
+ return nil unless key.respond_to?(:-)
436
+ n = find_nearest_node(key)
437
+ n == @nil_node ? nil : [n.key, n.value]
438
+ end
439
+
440
+ # Validates the red-black tree properties.
441
+ #
442
+ # Checks that:
443
+ # 1. Root is black
444
+ # 2. All paths from root to leaves have the same number of black nodes
445
+ # 3. No red node has a red child
446
+ # 4. Keys are properly ordered
447
+ #
448
+ # @return [Boolean] true if all properties are satisfied, false otherwise
449
+ def valid?
450
+ return false if @root.color == Node::RED
451
+ return false if check_black_height(@root) == -1
452
+ return false unless check_order(@root)
453
+ true
454
+ end
455
+
456
+ # @!visibility private
457
+ private
458
+
459
+ # Traverses the tree in ascending order (in-order traversal).
460
+ #
461
+ # @param node [Node] the current node
462
+ # @yield [key, value] each key-value pair in ascending order
463
+ # @return [void]
464
+ def traverse_asc(node, &block)
465
+ return if node == @nil_node
466
+ traverse_asc(node.left, &block)
467
+ yield node.key, node.value
468
+ traverse_asc(node.right, &block)
469
+ end
470
+
471
+ # Traverses the tree in descending order (reverse in-order traversal).
472
+ #
473
+ # @param node [Node] the current node
474
+ # @yield [key, value] each key-value pair in descending order
475
+ # @return [void]
476
+ def traverse_desc(node, &block)
477
+ return if node == @nil_node
478
+ traverse_desc(node.right, &block)
479
+ yield node.key, node.value
480
+ traverse_desc(node.left, &block)
481
+ end
482
+
483
+ # Traverses nodes with keys less than the specified key.
484
+ #
485
+ # @param node [Node] the current node
486
+ # @param key [Object] the upper bound (exclusive)
487
+ # @yield [key, value] each matching key-value pair
488
+ # @return [void]
489
+ def traverse_lt(node, key, &block)
490
+ return if node == @nil_node
491
+
492
+ traverse_lt(node.left, key, &block)
493
+ if (node.key <=> key) < 0
494
+ yield node.key, node.value
495
+ traverse_lt(node.right, key, &block)
496
+ end
497
+ end
498
+
499
+ # Traverses nodes with keys less than or equal to the specified key.
500
+ #
501
+ # @param node [Node] the current node
502
+ # @param key [Object] the upper bound (inclusive)
503
+ # @yield [key, value] each matching key-value pair
504
+ # @return [void]
505
+ def traverse_lte(node, key, &block)
506
+ return if node == @nil_node
507
+
508
+ traverse_lte(node.left, key, &block)
509
+ if (node.key <=> key) <= 0
510
+ yield node.key, node.value
511
+ traverse_lte(node.right, key, &block)
512
+ end
513
+ end
514
+
515
+ # Traverses nodes with keys greater than the specified key.
516
+ #
517
+ # @param node [Node] the current node
518
+ # @param key [Object] the lower bound (exclusive)
519
+ # @yield [key, value] each matching key-value pair
520
+ # @return [void]
521
+ def traverse_gt(node, key, &block)
522
+ return if node == @nil_node
523
+
524
+ if (node.key <=> key) > 0
525
+ traverse_gt(node.left, key, &block)
526
+ yield node.key, node.value
527
+ end
528
+ traverse_gt(node.right, key, &block)
529
+ end
530
+
531
+ # Traverses nodes with keys greater than or equal to the specified key.
532
+ #
533
+ # @param node [Node] the current node
534
+ # @param key [Object] the lower bound (inclusive)
535
+ # @yield [key, value] each matching key-value pair
536
+ # @return [void]
537
+ def traverse_gte(node, key, &block)
538
+ return if node == @nil_node
539
+
540
+ if (node.key <=> key) >= 0
541
+ traverse_gte(node.left, key, &block)
542
+ yield node.key, node.value
543
+ end
544
+ traverse_gte(node.right, key, &block)
545
+ end
546
+
547
+ # Traverses nodes with keys within the specified range.
548
+ #
549
+ # @param node [Node] the current node
550
+ # @param min [Object] the lower bound
551
+ # @param max [Object] the upper bound
552
+ # @param include_min [Boolean] whether to include the lower bound
553
+ # @param include_max [Boolean] whether to include the upper bound
554
+ # @yield [key, value] each matching key-value pair
555
+ # @return [void]
556
+ def traverse_between(node, min, max, include_min, include_max, &block)
557
+ return if node == @nil_node
558
+ if (node.key <=> min) > 0
559
+ traverse_between(node.left, min, max, include_min, include_max, &block)
560
+ end
561
+
562
+ greater = include_min ? (node.key <=> min) >= 0 : (node.key <=> min) > 0
563
+ less = include_max ? (node.key <=> max) <= 0 : (node.key <=> max) < 0
564
+
565
+ if greater && less
566
+ yield node.key, node.value
567
+ end
568
+
569
+ if (node.key <=> max) < 0
570
+ traverse_between(node.right, min, max, include_min, include_max, &block)
571
+ end
572
+ end
573
+
574
+ # Restores red-black tree properties after insertion.
575
+ #
576
+ # This method fixes any violations of red-black properties that may occur
577
+ # after inserting a new node (which is always colored red).
578
+ #
579
+ # @param z [Node] the newly inserted node
580
+ # @return [void]
581
+ def insert_fixup(z)
582
+ while z.parent.color == Node::RED
583
+ if z.parent == z.parent.parent.left
584
+ y = z.parent.parent.right
585
+ if y.color == Node::RED
586
+ z.parent.color = Node::BLACK
587
+ y.color = Node::BLACK
588
+ z.parent.parent.color = Node::RED
589
+ z = z.parent.parent
590
+ else
591
+ if z == z.parent.right
592
+ z = z.parent
593
+ left_rotate(z)
594
+ end
595
+ z.parent.color = Node::BLACK
596
+ z.parent.parent.color = Node::RED
597
+ right_rotate(z.parent.parent)
598
+ end
599
+ else
600
+ y = z.parent.parent.left
601
+ if y.color == Node::RED
602
+ z.parent.color = Node::BLACK
603
+ y.color = Node::BLACK
604
+ z.parent.parent.color = Node::RED
605
+ z = z.parent.parent
606
+ else
607
+ if z == z.parent.left
608
+ z = z.parent
609
+ right_rotate(z)
610
+ end
611
+ z.parent.color = Node::BLACK
612
+ z.parent.parent.color = Node::RED
613
+ left_rotate(z.parent.parent)
614
+ end
615
+ end
616
+ end
617
+ @root.color = Node::BLACK
618
+ end
619
+
620
+ # Finds and removes a node by key, returning its value.
621
+ #
622
+ # @param key [Object] the key to delete
623
+ # @return [Object, nil] the value of the deleted node, or nil if not found
624
+ def delete_node(key)
625
+ z = find_node(key)
626
+ return nil if z == @nil_node
627
+ remove_node(z)
628
+ end
629
+
630
+ # Removes a node from the tree and restores red-black properties.
631
+ #
632
+ # Handles three cases:
633
+ # 1. Node has no left child
634
+ # 2. Node has no right child
635
+ # 3. Node has both children (replace with inorder successor)
636
+ #
637
+ # @param z [Node] the node to remove
638
+ # @return [Object] the value of the removed node
639
+ def remove_node(z)
640
+ next_min_node = nil
641
+ if z == @min_node
642
+ if z.right != @nil_node
643
+ next_min_node = leftmost(z.right)
644
+ else
645
+ next_min_node = z.parent
646
+ end
647
+ end
648
+
649
+ y = z
650
+ y_original_color = y.color
651
+ if z.left == @nil_node
652
+ x = z.right
653
+ transplant(z, z.right)
654
+ elsif z.right == @nil_node
655
+ x = z.left
656
+ transplant(z, z.left)
657
+ else
658
+ y = leftmost(z.right)
659
+ y_original_color = y.color
660
+ x = y.right
661
+ if y.parent == z
662
+ x.parent = y
663
+ else
664
+ transplant(y, y.right)
665
+ y.right = z.right
666
+ y.right.parent = y
667
+ end
668
+ transplant(z, y)
669
+ y.left = z.left
670
+ y.left.parent = y
671
+ y.color = z.color
672
+ end
673
+ if y_original_color == Node::BLACK
674
+ delete_fixup(x)
675
+ end
676
+
677
+ if next_min_node
678
+ @min_node = next_min_node
679
+ end
680
+
681
+ z.value
682
+ end
683
+
684
+ # Restores red-black tree properties after deletion.
685
+ #
686
+ # This method fixes any violations of red-black properties that may occur
687
+ # after removing a black node from the tree.
688
+ #
689
+ # @param x [Node] the node that needs rebalancing
690
+ # @return [void]
691
+ def delete_fixup(x)
692
+ while x != @root && x.color == Node::BLACK
693
+ if x == x.parent.left
694
+ w = x.parent.right
695
+ if w.color == Node::RED
696
+ w.color = Node::BLACK
697
+ x.parent.color = Node::RED
698
+ left_rotate(x.parent)
699
+ w = x.parent.right
700
+ end
701
+ if w.left.color == Node::BLACK && w.right.color == Node::BLACK
702
+ w.color = Node::RED
703
+ x = x.parent
704
+ else
705
+ if w.right.color == Node::BLACK
706
+ w.left.color = Node::BLACK
707
+ w.color = Node::RED
708
+ right_rotate(w)
709
+ w = x.parent.right
710
+ end
711
+ w.color = x.parent.color
712
+ x.parent.color = Node::BLACK
713
+ w.right.color = Node::BLACK
714
+ left_rotate(x.parent)
715
+ x = @root
716
+ end
717
+ else
718
+ w = x.parent.left
719
+ if w.color == Node::RED
720
+ w.color = Node::BLACK
721
+ x.parent.color = Node::RED
722
+ right_rotate(x.parent)
723
+ w = x.parent.left
724
+ end
725
+ if w.right.color == Node::BLACK && w.left.color == Node::BLACK
726
+ w.color = Node::RED
727
+ x = x.parent
728
+ else
729
+ if w.left.color == Node::BLACK
730
+ w.right.color = Node::BLACK
731
+ w.color = Node::RED
732
+ left_rotate(w)
733
+ w = x.parent.left
734
+ end
735
+ w.color = x.parent.color
736
+ x.parent.color = Node::BLACK
737
+ w.left.color = Node::BLACK
738
+ right_rotate(x.parent)
739
+ x = @root
740
+ end
741
+ end
742
+ end
743
+ x.color = Node::BLACK
744
+ end
745
+
746
+ # Replaces subtree rooted at node u with subtree rooted at node v.
747
+ #
748
+ # @param u [Node] the node to be replaced
749
+ # @param v [Node] the replacement node
750
+ # @return [void]
751
+ def transplant(u, v)
752
+ if u.parent == @nil_node
753
+ @root = v
754
+ elsif u == u.parent.left
755
+ u.parent.left = v
756
+ else
757
+ u.parent.right = v
758
+ end
759
+ v.parent = u.parent
760
+ end
761
+
762
+ # Searches for a node with the given key.
763
+ #
764
+ # @param key [Object] the key to search for
765
+ # @return [Node] the found node, or @nil_node if not found
766
+ def find_node(key)
767
+ current = @root
768
+ while current != @nil_node
769
+ cmp = key <=> current.key
770
+ if cmp == 0
771
+ return current
772
+ elsif cmp < 0
773
+ current = current.left
774
+ else
775
+ current = current.right
776
+ end
777
+ end
778
+ @nil_node
779
+ end
780
+
781
+ # Finds the node with the closest key to the given key.
782
+ #
783
+ # Uses numeric distance (absolute difference) to determine proximity.
784
+ # If multiple nodes have the same distance, returns the one with the smaller key.
785
+ #
786
+ # @param key [Numeric] the target key
787
+ # @return [Node] the nearest node, or @nil_node if tree is empty
788
+ def find_nearest_node(key)
789
+ current = @root
790
+ closest = @nil_node
791
+ min_dist = nil
792
+
793
+ while current != @nil_node
794
+ cmp = key <=> current.key
795
+ if cmp == 0
796
+ return current
797
+ end
798
+
799
+ # For nearest, we still typically rely on numeric distance.
800
+ # If keys are strings, this part will fail unless they support -.
801
+ dist = (current.key - key).abs
802
+
803
+ if closest == @nil_node || dist < min_dist
804
+ min_dist = dist
805
+ closest = current
806
+ elsif dist == min_dist
807
+ if (current.key <=> closest.key) < 0
808
+ closest = current
809
+ end
810
+ end
811
+
812
+ if cmp < 0
813
+ current = current.left
814
+ else
815
+ current = current.right
816
+ end
817
+ end
818
+ closest
819
+ end
820
+
821
+ # Finds the leftmost (minimum) node in a subtree.
822
+ #
823
+ # @param node [Node] the root of the subtree
824
+ # @return [Node] the leftmost node
825
+ def leftmost(node)
826
+ while node.left != @nil_node
827
+ node = node.left
828
+ end
829
+ node
830
+ end
831
+
832
+ # Finds the rightmost (maximum) node in a subtree.
833
+ #
834
+ # @param node [Node] the root of the subtree
835
+ # @return [Node] the rightmost node
836
+ def rightmost(node)
837
+ while node.right != @nil_node
838
+ node = node.right
839
+ end
840
+ node
841
+ end
842
+
843
+ # Performs a left rotation on the given node.
844
+ #
845
+ # Transforms the tree structure:
846
+ # x y
847
+ # / \ / \
848
+ # a y => x c
849
+ # / \ / \
850
+ # b c a b
851
+ #
852
+ # @param x [Node] the node to rotate
853
+ # @return [void]
854
+ def left_rotate(x)
855
+ y = x.right
856
+ x.right = y.left
857
+ if y.left != @nil_node
858
+ y.left.parent = x
859
+ end
860
+ y.parent = x.parent
861
+ if x.parent == @nil_node
862
+ @root = y
863
+ elsif x == x.parent.left
864
+ x.parent.left = y
865
+ else
866
+ x.parent.right = y
867
+ end
868
+ y.left = x
869
+ x.parent = y
870
+ end
871
+
872
+ # Performs a right rotation on the given node.
873
+ #
874
+ # Transforms the tree structure:
875
+ # y x
876
+ # / \ / \
877
+ # x c => a y
878
+ # / \ / \
879
+ # a b b c
880
+ #
881
+ # @param y [Node] the node to rotate
882
+ # @return [void]
883
+ def right_rotate(y)
884
+ x = y.left
885
+ y.left = x.right
886
+ if x.right != @nil_node
887
+ x.right.parent = y
888
+ end
889
+ x.parent = y.parent
890
+ if y.parent == @nil_node
891
+ @root = x
892
+ elsif y == y.parent.right
893
+ y.parent.right = x
894
+ else
895
+ y.parent.left = x
896
+ end
897
+ x.right = y
898
+ y.parent = x
899
+ end
900
+
901
+ # Recursively checks black height consistency.
902
+ #
903
+ # Verifies that:
904
+ # - No red node has a red child
905
+ # - All paths have the same black height
906
+ #
907
+ # @param node [Node] the current node
908
+ # @return [Integer] the black height, or -1 if invalid
909
+ def check_black_height(node)
910
+ return 0 if node == @nil_node
911
+
912
+ if node.color == Node::RED
913
+ return -1 if node.left.color == Node::RED || node.right.color == Node::RED
914
+ end
915
+
916
+ left_h = check_black_height(node.left)
917
+ right_h = check_black_height(node.right)
918
+
919
+ return -1 if left_h == -1 || right_h == -1 || left_h != right_h
920
+
921
+ left_h + (node.color == Node::BLACK ? 1 : 0)
922
+ end
923
+
924
+ def check_order(node)
925
+ return true if node == @nil_node
926
+ if node.left != @nil_node && (node.left.key <=> node.key) >= 0
927
+ return false
928
+ end
929
+ if node.right != @nil_node && (node.right.key <=> node.key) <= 0
930
+ return false
931
+ end
932
+ check_order(node.left) && check_order(node.right)
933
+ end
934
+ end
935
+
936
+ # A Multi Red-Black Tree that allows duplicate keys.
937
+ #
938
+ # MultiRBTree extends RBTree to support multiple values per key. Each key maps to
939
+ # a linked list of values rather than a single value. The size reflects the total
940
+ # number of key-value pairs (not unique keys).
941
+ #
942
+ # == Features
943
+ #
944
+ # * Multiple values per key using linked lists
945
+ # * Separate methods for single deletion (`delete_one`) vs. all deletions (`delete`)
946
+ # * Values for each key maintain insertion order
947
+ # * min/max return first/last values respectively
948
+ #
949
+ # == Usage
950
+ #
951
+ # tree = MultiRBTree.new
952
+ # tree.insert(1, 'first one')
953
+ # tree.insert(1, 'second one')
954
+ # tree.insert(2, 'two')
955
+ #
956
+ # tree.size # => 3 (total key-value pairs)
957
+ # tree.get(1) # => "first one" (first value)
958
+ # tree.get_all(1) # => ["first one", "second one"] (all values)
959
+ #
960
+ # tree.delete_one(1) # removes only "first one"
961
+ # tree.get(1) # => "second one"
962
+ #
963
+ # tree.delete(1) # removes all remaining values for key 1
964
+ #
965
+ # @author Masahito Suzuki
966
+ # @since 0.1.2
967
+ class MultiRBTree < RBTree
968
+ # Retrieves the first value associated with the given key.
969
+ #
970
+ # @param key [Object] the key to look up
971
+ # @return [Object, nil] the first value for the key, or nil if not found
972
+ # @example
973
+ # tree = MultiRBTree.new
974
+ # tree.insert(1, 'first')
975
+ # tree.insert(1, 'second')
976
+ # tree.get(1) # => "first"
977
+ def get(key)
978
+ n = find_node(key)
979
+ n == @nil_node || n.value.empty? ? nil : n.value.first
980
+ end
981
+ alias_method :[], :get
982
+
983
+ # Retrieves all values associated with the given key.
984
+ #
985
+ # @param key [Object] the key to look up
986
+ # @return [Array, nil] an Array containing all values, or nil if not found
987
+ # @example
988
+ # tree = MultiRBTree.new
989
+ # tree.insert(1, 'first')
990
+ # tree.insert(1, 'second')
991
+ # tree.get_all(1).to_a # => ["first", "second"]
992
+ def get_all(key)
993
+ n = find_node(key)
994
+ n == @nil_node || n.value.empty? ? nil : n.value
995
+ end
996
+
997
+ # Inserts a value for the given key.
998
+ #
999
+ # If the key already exists, the value is appended to its list.
1000
+ # If the key doesn't exist, a new node is created.
1001
+ #
1002
+ # @param key [Object] the key (must implement <=>)
1003
+ # @param value [Object] the value to insert
1004
+ # @return [Boolean] always returns true
1005
+ # @example
1006
+ # tree = MultiRBTree.new
1007
+ # tree.insert(1, 'first')
1008
+ # tree.insert(1, 'second') # adds another value for key 1
1009
+ def insert(key, value)
1010
+ y = @nil_node
1011
+ x = @root
1012
+ while x != @nil_node
1013
+ y = x
1014
+ cmp = key <=> x.key
1015
+ if cmp == 0
1016
+ x.value << value
1017
+ @size += 1
1018
+ return true
1019
+ elsif cmp < 0
1020
+ x = x.left
1021
+ else
1022
+ x = x.right
1023
+ end
1024
+ end
1025
+ z = Node.new(key, [value], Node::RED, @nil_node, @nil_node, @nil_node)
1026
+ z.parent = y
1027
+ if y == @nil_node
1028
+ @root = z
1029
+ elsif (key <=> y.key) < 0
1030
+ y.left = z
1031
+ else
1032
+ y.right = z
1033
+ end
1034
+ z.left = @nil_node
1035
+ z.right = @nil_node
1036
+ z.color = Node::RED
1037
+ insert_fixup(z)
1038
+ @size += 1
1039
+
1040
+ if @min_node == @nil_node || (key <=> @min_node.key) < 0
1041
+ @min_node = z
1042
+ end
1043
+
1044
+ true
1045
+ end
1046
+
1047
+ # Deletes only the first value for the specified key.
1048
+ #
1049
+ # If the key has multiple values, removes only the first one.
1050
+ # If this was the last value for the key, the node is removed from the tree.
1051
+ #
1052
+ # @param key [Object] the key to delete from
1053
+ # @return [Object, nil] the deleted value, or nil if key not found
1054
+ # @example
1055
+ # tree = MultiRBTree.new
1056
+ # tree.insert(1, 'first')
1057
+ # tree.insert(1, 'second')
1058
+ # tree.delete_one(1) # => "first"
1059
+ # tree.get(1) # => "second"
1060
+ def delete_one(key)
1061
+ z = find_node(key)
1062
+ return nil if z == @nil_node
1063
+
1064
+ value = z.value.shift
1065
+ @size -= 1
1066
+ if z.value.empty?
1067
+ remove_node(z)
1068
+ end
1069
+ value
1070
+ end
1071
+
1072
+ # Deletes all values for the specified key.
1073
+ #
1074
+ # Removes the node and all associated values.
1075
+ #
1076
+ # @param key [Object] the key to delete
1077
+ # @return [Array, nil] the array of all deleted values, or nil if not found
1078
+ # @example
1079
+ # tree = MultiRBTree.new
1080
+ # tree.insert(1, 'first')
1081
+ # tree.insert(1, 'second')
1082
+ # vals = tree.delete(1) # removes both values
1083
+ # vals.size # => 2
1084
+ def delete(key)
1085
+ z = find_node(key)
1086
+ return nil if z == @nil_node
1087
+
1088
+ count = z.value.size
1089
+ remove_node(z)
1090
+ @size -= count
1091
+ z.value
1092
+ end
1093
+
1094
+ def shift
1095
+ return nil if @min_node == @nil_node
1096
+ node = @min_node
1097
+ key = node.key
1098
+ val = node.value.first
1099
+ node.value.shift
1100
+ @size -= 1
1101
+ if node.value.empty?
1102
+ remove_node(node)
1103
+ end
1104
+ [key, val]
1105
+ end
1106
+
1107
+ def pop
1108
+ n = rightmost(@root)
1109
+ return nil if n == @nil_node
1110
+ val = n.value.last
1111
+ n.value.pop
1112
+ @size -= 1
1113
+ if n.value.empty?
1114
+ remove_node(n)
1115
+ end
1116
+ [n.key, val]
1117
+ end
1118
+
1119
+ def min
1120
+ return nil if @min_node == @nil_node || @min_node.value.empty?
1121
+ [@min_node.key, @min_node.value.first]
1122
+ end
1123
+
1124
+ def max
1125
+ n = rightmost(@root)
1126
+ n == @nil_node || n.value.empty? ? nil : [n.key, n.value.first]
1127
+ end
1128
+
1129
+ def nearest(key)
1130
+ (n = super(key)) ? [n[0], n[1].first] : nil
1131
+ end
1132
+
1133
+ private
1134
+
1135
+ def traverse_asc(node, &block)
1136
+ return if node == @nil_node
1137
+ traverse_asc(node.left, &block)
1138
+ node.value.each { |v| yield node.key, v }
1139
+ traverse_asc(node.right, &block)
1140
+ end
1141
+
1142
+ def traverse_desc(node, &block)
1143
+ return if node == @nil_node
1144
+ traverse_desc(node.right, &block)
1145
+ node.value.reverse_each { |v| yield node.key, v }
1146
+ traverse_desc(node.left, &block)
1147
+ end
1148
+
1149
+ def traverse_lt(node, key, &block)
1150
+ return if node == @nil_node
1151
+
1152
+ traverse_lt(node.left, key, &block)
1153
+ if (node.key <=> key) < 0
1154
+ node.value.each { |v| yield node.key, v }
1155
+ traverse_lt(node.right, key, &block)
1156
+ end
1157
+ end
1158
+
1159
+ def traverse_lte(node, key, &block)
1160
+ return if node == @nil_node
1161
+
1162
+ traverse_lte(node.left, key, &block)
1163
+ if (node.key <=> key) <= 0
1164
+ node.value.each { |v| yield node.key, v }
1165
+ traverse_lte(node.right, key, &block)
1166
+ end
1167
+ end
1168
+
1169
+ def traverse_gt(node, key, &block)
1170
+ return if node == @nil_node
1171
+
1172
+ if (node.key <=> key) > 0
1173
+ traverse_gt(node.left, key, &block)
1174
+ node.value.each { |v| yield node.key, v }
1175
+ end
1176
+ traverse_gt(node.right, key, &block)
1177
+ end
1178
+
1179
+ def traverse_gte(node, key, &block)
1180
+ return if node == @nil_node
1181
+
1182
+ if (node.key <=> key) >= 0
1183
+ traverse_gte(node.left, key, &block)
1184
+ node.value.each { |v| yield node.key, v }
1185
+ end
1186
+ traverse_gte(node.right, key, &block)
1187
+ end
1188
+
1189
+ def traverse_between(node, min, max, include_min, include_max, &block)
1190
+ return if node == @nil_node
1191
+ if (node.key <=> min) > 0
1192
+ traverse_between(node.left, min, max, include_min, include_max, &block)
1193
+ end
1194
+
1195
+ greater = include_min ? (node.key <=> min) >= 0 : (node.key <=> min) > 0
1196
+ less = include_max ? (node.key <=> max) <= 0 : (node.key <=> max) < 0
1197
+
1198
+ if greater && less
1199
+ node.value.each { |v| yield node.key, v }
1200
+ end
1201
+
1202
+ if (node.key <=> max) < 0
1203
+ traverse_between(node.right, min, max, include_min, include_max, &block)
1204
+ end
1205
+ end
1206
+ end
1207
+
1208
+ # Internal node structure for RBTree.
1209
+ #
1210
+ # Each node stores a key-value pair, color (red or black), and references
1211
+ # to parent, left child, and right child nodes.
1212
+ #
1213
+ # @!attribute [rw] key
1214
+ # @return [Object] the key stored in this node
1215
+ # @!attribute [rw] value
1216
+ # @return [Object] the value stored in this node
1217
+ # @!attribute [rw] color
1218
+ # @return [Symbol] the color of the node (:red or :black)
1219
+ # @!attribute [rw] left
1220
+ # @return [Node] the left child node
1221
+ # @!attribute [rw] right
1222
+ # @return [Node] the right child node
1223
+ # @!attribute [rw] parent
1224
+ # @return [Node] the parent node
1225
+ #
1226
+ # @api private
1227
+ class RBTree::Node
1228
+ attr_accessor :key, :value, :color, :left, :right, :parent
1229
+
1230
+ # Red color constant
1231
+ RED = :red
1232
+ # Black color constant
1233
+ BLACK = :black
1234
+
1235
+ # Creates a new Node.
1236
+ #
1237
+ # @param key [Object] the key
1238
+ # @param value [Object] the value
1239
+ # @param color [Symbol] the color (:red or :black)
1240
+ # @param left [Node] the left child
1241
+ # @param right [Node] the right child
1242
+ # @param parent [Node] the parent node
1243
+ def initialize(key = nil, value = nil, color = BLACK, left = nil, right = nil, parent = nil)
1244
+ @key = key
1245
+ @value = value
1246
+ @color = color
1247
+ @left = left
1248
+ @right = right
1249
+ @parent = parent
1250
+ end
1251
+
1252
+ # Checks if the node is red.
1253
+ # @return [Boolean] true if red, false otherwise
1254
+ def red? = @color == RED
1255
+
1256
+ # Checks if the node is black.
1257
+ # @return [Boolean] true if black, false otherwise
1258
+ def black? = @color == BLACK
1259
+ end
1260
+