Class: RBTree
- Inherits:
-
Object
- Object
- RBTree
- Includes:
- Enumerable
- Defined in:
- lib/rbtree.rb,
lib/rbtree/version.rb
Overview
A Red-Black Tree implementation providing efficient ordered key-value storage.
RBTree is a self-balancing binary search tree that maintains sorted order of keys and provides O(log n) time complexity for insertion, deletion, and lookup operations. The tree enforces the following red-black properties to maintain balance:
- Every node is either red or black
- The root is always black
- All leaves (nil nodes) are black
- Red nodes cannot have red children
- All paths from root to leaves contain the same number of black nodes
Features
- Ordered iteration over key-value pairs
- Range queries (less than, greater than, between)
- Efficient min/max retrieval
- Nearest key search for numeric keys
- Tree integrity validation
Usage
# Create an empty tree
tree = RBTree.new
# Create from a hash
tree = RBTree.new({3 => 'three', 1 => 'one', 2 => 'two'})
# Create from an array of key-value pairs
tree = RBTree.new([[3, 'three'], [1, 'one'], [2, 'two']])
# Create using bracket notation
tree = RBTree[3 => 'three', 1 => 'one', 2 => 'two']
# Insert and retrieve values
tree.insert(5, 'five')
tree[4] = 'four'
puts tree[4] # => "four"
# Iterate in sorted order
tree.each { |key, value| puts "#{key}: #{value}" }
Performance
All major operations (insert, delete, search) run in O(log n) time. Iteration over all elements takes O(n) time.
Direct Known Subclasses
Defined Under Namespace
Classes: AutoShrinkNodePool, Node, NodeAllocator, NodePool
Constant Summary collapse
- VERSION =
The version of the rbtree-ruby gem
"0.4.0"
Instance Attribute Summary collapse
-
#key_count ⇒ Integer
readonly
Returns the number of key-value pairs stored in the tree.
Class Method Summary collapse
-
.[](*args) ⇒ RBTree
Creates a new RBTree from the given arguments.
-
.coherent_key_class(klass) ⇒ Class
Declares that (a <=> b) == 0 and
a.eql?(b)agree for instances of the given key class, speeding up lookups that miss the internal hash index.
Instance Method Summary collapse
-
#[](key_or_range) ⇒ Object, ...
Retrieves a value associated with the given key, or a range of entries if a Range is provided.
-
#between(min, max, include_min: true, include_max: true, reverse: false, safe: false) {|key, value| ... } ⇒ Enumerator, RBTree
Retrieves all key-value pairs with keys within the specified range.
-
#clear ⇒ RBTree
Removes all key-value pairs from the tree.
-
#delete_if {|key, value| ... } ⇒ RBTree, Enumerator
Deletes key-value pairs for which the block returns true.
-
#delete_key(key) ⇒ Object?
(also: #delete)
Deletes the key-value pair with the specified key.
-
#each(reverse: false, safe: false) {|key, value| ... } ⇒ Enumerator, RBTree
Iterates over all key-value pairs in ascending (or descending) order.
-
#empty? ⇒ Boolean
Checks if the tree is empty.
-
#first(n = nil) ⇒ Array?
Returns the first key-value pair, or the first
npairs, without removing them. -
#gt(key, reverse: false, safe: false) {|key, value| ... } ⇒ Enumerator, RBTree
Retrieves all key-value pairs with keys greater than the specified key.
-
#gte(key, reverse: false, safe: false) {|key, value| ... } ⇒ Enumerator, RBTree
Retrieves all key-value pairs with keys greater than or equal to the specified key.
-
#has_key?(key) ⇒ Boolean
(also: #key?)
Checks if the tree contains the given key.
-
#initialize(*args, overwrite: true, node_allocator: AutoShrinkNodePool.new, &block) ⇒ RBTree
constructor
Initializes a new RBTree.
-
#initialize_copy(orig) ⇒ void
Creates a deep copy of the tree.
-
#insert(*args, overwrite: @overwrite, &block) ⇒ Boolean?
(also: #[]=)
Inserts one or more key-value pairs into the tree.
-
#inspect ⇒ String
Returns a string representation of the tree.
-
#invert ⇒ RBTree, MultiRBTree
Returns a new tree with keys and values swapped.
-
#keep_if {|key, value| ... } ⇒ RBTree, Enumerator
Keeps key-value pairs for which the block returns true, deleting the rest.
-
#keys(reverse: false, safe: false) {|key| ... } ⇒ Enumerator, RBTree
Iterates over all keys in ascending (or descending) order.
-
#last(n = nil) ⇒ Array?
Returns the last key-value pair, or the last
npairs, without removing them. -
#lt(key, reverse: false, safe: false) {|key, value| ... } ⇒ Enumerator, RBTree
Retrieves all key-value pairs with keys less than the specified key.
-
#lte(key, reverse: false, safe: false) {|key, value| ... } ⇒ Enumerator, RBTree
Retrieves all key-value pairs with keys less than or equal to the specified key.
-
#max(*args, &block) ⇒ Array?
Returns the maximum key-value pair without removing it.
-
#max_key ⇒ Object?
Returns the maximum key without removing it.
-
#merge(other) {|key, old_value, new_value| ... } ⇒ RBTree
Returns a new tree containing the merged contents of self and other.
-
#merge!(other, overwrite: true) {|key, old_value, new_value| ... } ⇒ RBTree
Merges the contents of another tree, hash, or enumerable into this tree.
-
#min(*args, &block) ⇒ Array?
Returns the minimum key-value pair without removing it.
-
#min_key ⇒ Object?
Returns the minimum key without removing it.
-
#nearest(key) ⇒ Array(Object, Object)?
Returns the key-value pair with the key closest to the given key.
-
#nearest_key(key) ⇒ Object?
Returns the key with the key closest to the given key.
-
#pop ⇒ Array(Object, Object)?
Removes and returns the maximum key-value pair.
-
#prev(key) ⇒ Array(Object, Object)?
Returns the key-value pair with the largest key that is smaller than the given key.
-
#prev_key(key) ⇒ Object?
Returns the key with the largest key that is smaller than the given key.
-
#reject {|key, value| ... } ⇒ RBTree, Enumerator
Returns a new tree containing key-value pairs for which the block returns false.
-
#reject! {|key, value| ... } ⇒ RBTree, ...
Deletes key-value pairs for which the block returns true.
-
#reverse_each(safe: false) {|key, value| ... } ⇒ Enumerator, RBTree
Iterates over all key-value pairs in descending order of keys.
-
#select {|key, value| ... } ⇒ RBTree, Enumerator
Returns a new tree containing key-value pairs for which the block returns true.
-
#shift ⇒ Array(Object, Object)?
Removes and returns the minimum key-value pair.
-
#size ⇒ Integer
(also: #value_count)
Returns the number of key-value pairs stored in the tree.
-
#succ(key) ⇒ Array(Object, Object)?
Returns the key-value pair with the smallest key that is larger than the given key.
-
#succ_key(key) ⇒ Object?
Returns the key with the smallest key that is larger than the given key.
-
#to_h ⇒ Hash
Returns a Hash containing all key-value pairs from the tree, in ascending key order.
-
#valid? ⇒ Boolean
Validates the red-black tree properties and the auxiliary structures.
-
#value(key) ⇒ Object?
(also: #get)
Retrieves the value associated with the given key.
Constructor Details
#initialize(*args, overwrite: true, node_allocator: AutoShrinkNodePool.new, &block) ⇒ RBTree
Initializes a new RBTree.
The tree can be initialized empty or populated with initial data from a Hash, Array, or Enumerator. A block can also be provided to supply the initial data.
118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 |
# File 'lib/rbtree.rb', line 118 def initialize(*args, overwrite: true, node_allocator: AutoShrinkNodePool.new, &block) @nil_node = Node.new @nil_node.color = Node::BLACK @nil_node.left = @nil_node @nil_node.right = @nil_node @root = @nil_node @min_node = @nil_node @max_node = @nil_node @hash_index = {} # Hash index for O(1) key lookup, one entry per node @node_allocator = node_allocator @key_count = 0 @mod_count = 0 # bumped by changes a traversal can observe @key_class = nil # single class of all keys, or false once mixed @coherent_keys = false @overwrite = overwrite if args.size > 0 || block_given? insert(*args, overwrite: overwrite, &block) end end |
Instance Attribute Details
#key_count ⇒ Integer (readonly)
Returns the number of key-value pairs stored in the tree.
82 83 84 |
# File 'lib/rbtree.rb', line 82 def key_count @key_count end |
Class Method Details
.[](*args) ⇒ RBTree
Creates a new RBTree from the given arguments.
This is a convenience method equivalent to RBTree.new(*args).
92 93 94 |
# File 'lib/rbtree.rb', line 92 def self.[](*args) new(*args) end |
.coherent_key_class(klass) ⇒ Class
Declares that (a <=> b) == 0 and a.eql?(b) agree for instances of the
given key class, speeding up lookups that miss the internal hash index.
Optimization hint only: undeclared classes are still handled correctly, at O(log n) per missed lookup. Declaring a class that does not satisfy this makes such lookups report a present key as absent.
75 76 77 78 |
# File 'lib/rbtree.rb', line 75 def self.coherent_key_class(klass) COHERENT_KEY_CLASSES[klass] = true klass end |
Instance Method Details
#[](key_or_range) ⇒ Object, ...
Retrieves a value associated with the given key, or a range of entries if a Range is provided.
284 285 286 287 288 289 290 291 292 293 294 295 296 297 |
# File 'lib/rbtree.rb', line 284 def [](key_or_range, **) return value(key_or_range, **) if !key_or_range.is_a?(Range) r = key_or_range r.begin ? ( r.end ? between(r.begin, r.end, include_max: !r.exclude_end?, **) : gte(r.begin, **) ) : ( r.end ? (r.exclude_end? ? lt(r.end, **) : lte(r.end, **)) : each(**) ) end |
#between(min, max, include_min: true, include_max: true, reverse: false, safe: false) {|key, value| ... } ⇒ Enumerator, RBTree
Retrieves all key-value pairs with keys within the specified range.
718 719 720 721 722 |
# File 'lib/rbtree.rb', line 718 def between(min, max, include_min: true, include_max: true, reverse: false, safe: false, &block) return enum_for(__method__, min, max, include_min: include_min, include_max: include_max, reverse: reverse, safe: safe) unless block_given? traverse_range(reverse, min, max, include_min, include_max, safe: safe, &block) self end |
#clear ⇒ RBTree
Removes all key-value pairs from the tree.
Runs in O(1): the nodes are left to the garbage collector, and the allocator is told of the bulk discard so that pool statistics stay accurate.
545 546 547 548 549 550 551 552 553 554 |
# File 'lib/rbtree.rb', line 545 def clear @node_allocator.discard(@key_count) if @key_count > 0 @root = @min_node = @max_node = @nil_node @hash_index.clear @key_count = 0 @key_class = nil @coherent_keys = false @mod_count += 1 self end |
#delete_if {|key, value| ... } ⇒ RBTree, Enumerator
Deletes key-value pairs for which the block returns true. Modifies the tree in place.
771 772 773 774 775 |
# File 'lib/rbtree.rb', line 771 def delete_if(&block) return enum_for(__method__) { size } unless block_given? each(safe: true) { |k, v| delete(k) if block.call(k, v) } self end |
#delete_key(key) ⇒ Object? Also known as: delete
Deletes the key-value pair with the specified key.
Entries whose value is nil or false are deleted correctly, so the return
value alone cannot distinguish them from a missing key; use #has_key? first
if that matters.
503 504 505 506 507 508 |
# File 'lib/rbtree.rb', line 503 def delete_key(key) return nil unless (z = find_node(key)) value = z.value delete_found_node(z) value end |
#each(reverse: false, safe: false) {|key, value| ... } ⇒ Enumerator, RBTree
Iterates over all key-value pairs in ascending (or descending) order.
605 606 607 608 609 |
# File 'lib/rbtree.rb', line 605 def each(reverse: false, safe: false, &block) return enum_for(__method__, reverse: reverse, safe: safe) { size } unless block_given? traverse_range(reverse, nil, nil, false, false, safe: safe, &block) self end |
#empty? ⇒ Boolean
Checks if the tree is empty.
166 |
# File 'lib/rbtree.rb', line 166 def empty? = @hash_index.empty? |
#first(n = nil) ⇒ Array?
Returns the first key-value pair, or the first n pairs, without removing them.
229 |
# File 'lib/rbtree.rb', line 229 def first(n = nil) = n.nil? ? min : take(n) |
#gt(key, reverse: false, safe: false) {|key, value| ... } ⇒ Enumerator, RBTree
Retrieves all key-value pairs with keys greater than the specified key.
681 682 683 684 685 |
# File 'lib/rbtree.rb', line 681 def gt(key, reverse: false, safe: false, &block) return enum_for(__method__, key, reverse: reverse, safe: safe) unless block_given? traverse_range(reverse, key, nil, false, false, safe: safe, &block) self end |
#gte(key, reverse: false, safe: false) {|key, value| ... } ⇒ Enumerator, RBTree
Retrieves all key-value pairs with keys greater than or equal to the specified key.
698 699 700 701 702 |
# File 'lib/rbtree.rb', line 698 def gte(key, reverse: false, safe: false, &block) return enum_for(__method__, key, reverse: reverse, safe: safe) unless block_given? traverse_range(reverse, key, nil, true, false, safe: safe, &block) self end |
#has_key?(key) ⇒ Boolean Also known as: key?
Checks if the tree contains the given key.
A key counts as present when (key <=> stored_key) == 0, even if the two
objects are not eql? (e.g. 1.0 finds a stored 1).
259 |
# File 'lib/rbtree.rb', line 259 def has_key?(key) = @hash_index.key?(key) || !find_node_by_order(key).nil? |
#initialize_copy(orig) ⇒ void
This method returns an undefined value.
Creates a deep copy of the tree.
Called automatically by dup and clone.
The copy shares the original's node allocator instance.
147 148 149 150 151 152 |
# File 'lib/rbtree.rb', line 147 def initialize_copy(orig) initialize( overwrite: orig.instance_variable_get(:@overwrite), node_allocator: orig.instance_variable_get(:@node_allocator)) orig.each { |k, v| insert(k, v) } end |
#insert(*args, overwrite: @overwrite, &block) ⇒ Boolean? Also known as: []=
Inserts one or more key-value pairs into the tree.
This method supports both single entry insertion and bulk insertion.
Single insertion:
insert(key, value, overwrite: true)
Bulk insertion:
insert(hash, overwrite: true)
insert(array_of_pairs, overwrite: true)
insert(enumerator, overwrite: true)
insert { data_source }
If the key already exists and overwrite is true (default), the value is updated. If overwrite is false and the key exists, the operation returns nil without modification.
408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 |
# File 'lib/rbtree.rb', line 408 def insert(*args, overwrite: @overwrite, &block) if args.size == 2 key, value = args insert_entry(key, value, overwrite: overwrite) else source = nil if args.empty? && block_given? source = yield elsif args.size == 1 source = args[0] elsif args.empty? return # No-op else raise ArgumentError, "wrong number of arguments (given #{args.size}, expected 0..2)" end return if source.nil? unless source.respond_to?(:each) raise ArgumentError, "Source must be iterable" end # Self-insertion (e.g. tree.merge!(tree)) must not mutate what it iterates. source = source.to_a if source.equal?(self) source.each do |*pair| key, value = nil, nil if pair.size == 1 && pair[0].is_a?(Array) key, value = pair[0] raise ArgumentError, "Invalid pair size: #{pair[0].size} (expected 2)" unless pair[0].size == 2 elsif pair.size == 2 key, value = pair else raise ArgumentError, "Invalid pair format: #{pair.inspect}" end insert_entry(key, value, overwrite: overwrite) end end end |
#inspect ⇒ String
Returns a string representation of the tree.
Shows the first 5 entries and total size. Useful for debugging.
795 796 797 798 799 |
# File 'lib/rbtree.rb', line 795 def inspect content = take(5).map { |k, v| "#{k.inspect}=>#{v.inspect}" }.join(", ") suffix = size > 5 ? ", ..." : "" "#<#{self.class}:0x#{object_id.to_s(16)} size=#{size} {#{content}#{suffix}}>" end |
#invert ⇒ RBTree, MultiRBTree
Returns a new tree with keys and values swapped.
For RBTree, duplicate values result in later keys overwriting earlier ones. For MultiRBTree, all key-value pairs are preserved. Values must implement <=> to serve as keys in the new tree.
784 785 786 787 788 |
# File 'lib/rbtree.rb', line 784 def invert result = new_derived_tree each { |k, v| result.insert(v, k) } result end |
#keep_if {|key, value| ... } ⇒ RBTree, Enumerator
Keeps key-value pairs for which the block returns true, deleting the rest. Modifies the tree in place.
761 762 763 764 765 |
# File 'lib/rbtree.rb', line 761 def keep_if(&block) return enum_for(__method__) { size } unless block_given? each(safe: true) { |k, v| delete(k) unless block.call(k, v) } self end |
#keys(reverse: false, safe: false) {|key| ... } ⇒ Enumerator, RBTree
Iterates over all keys in ascending (or descending) order.
577 578 579 580 581 582 |
# File 'lib/rbtree.rb', line 577 def keys(reverse: false, safe: false, &block) # `size`, not `key_count`: MultiRBTree yields a key once per value it holds. return enum_for(__method__, reverse: reverse, safe: safe) { size } unless block_given? each(reverse: reverse, safe: safe) { |key, _| yield key } self end |
#last(n = nil) ⇒ Array?
Returns the last key-value pair, or the last n pairs, without removing them.
239 240 241 242 243 244 245 |
# File 'lib/rbtree.rb', line 239 def last(n = nil) return max if n.nil? result = [] reverse_each { |pair| break if result.size >= n; result << pair } result.reverse! result end |
#lt(key, reverse: false, safe: false) {|key, value| ... } ⇒ Enumerator, RBTree
Retrieves all key-value pairs with keys less than the specified key.
647 648 649 650 651 |
# File 'lib/rbtree.rb', line 647 def lt(key, reverse: false, safe: false, &block) return enum_for(__method__, key, reverse: reverse, safe: safe) unless block_given? traverse_range(reverse, nil, key, false, false, safe: safe, &block) self end |
#lte(key, reverse: false, safe: false) {|key, value| ... } ⇒ Enumerator, RBTree
Retrieves all key-value pairs with keys less than or equal to the specified key.
664 665 666 667 668 |
# File 'lib/rbtree.rb', line 664 def lte(key, reverse: false, safe: false, &block) return enum_for(__method__, key, reverse: reverse, safe: safe) unless block_given? traverse_range(reverse, nil, key, false, true, safe: safe, &block) self end |
#max(*args, &block) ⇒ Array?
Returns the maximum key-value pair without removing it.
With no argument and no block this is an O(1) cached lookup; given a count or a
comparison block, Enumerable#max semantics apply instead.
216 217 218 219 |
# File 'lib/rbtree.rb', line 216 def max(*args, &block) return super if !args.empty? || block max_node&.pair end |
#max_key ⇒ Object?
Returns the maximum key without removing it.
203 |
# File 'lib/rbtree.rb', line 203 def max_key = max_node&.key |
#merge(other) {|key, old_value, new_value| ... } ⇒ RBTree
Returns a new tree containing the merged contents of self and other.
When a block is given, it is called with (key, old_value, new_value) for duplicate keys, and the block's return value is used.
457 458 459 |
# File 'lib/rbtree.rb', line 457 def merge(other, &block) dup.merge!(other, &block) end |
#merge!(other, overwrite: true) {|key, old_value, new_value| ... } ⇒ RBTree
Merges the contents of another tree, hash, or enumerable into this tree.
When a block is given, it is called with (key, old_value, new_value) for duplicate keys, and the block's return value is used.
470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 |
# File 'lib/rbtree.rb', line 470 def merge!(other, overwrite: true, &block) if defined?(MultiRBTree) && other.is_a?(MultiRBTree) raise ArgumentError, "Cannot merge MultiRBTree into RBTree" end if block other_enum = other.is_a?(Hash) || other.is_a?(RBTree) ? other : other.each # Snapshot on self-merge; see RBTree#insert. other_enum = other_enum.to_a if other_enum.equal?(self) other_enum.each do |k, v| if has_key?(k) insert_entry(k, block.call(k, value(k), v), overwrite: true) else insert_entry(k, v) end end else insert(other, overwrite: overwrite) end self end |
#min(*args, &block) ⇒ Array?
Returns the minimum key-value pair without removing it.
With no argument and no block this is an O(1) cached lookup; given a count or a
comparison block, Enumerable#min semantics apply instead.
192 193 194 195 |
# File 'lib/rbtree.rb', line 192 def min(*args, &block) return super if !args.empty? || block min_node&.pair end |
#min_key ⇒ Object?
Returns the minimum key without removing it.
179 |
# File 'lib/rbtree.rb', line 179 def min_key = min_node&.key |
#nearest(key) ⇒ Array(Object, Object)?
Returns the key-value pair with the key closest to the given key.
This method requires keys to be numeric or support subtraction and abs methods. If multiple keys have the same distance, the one with the smaller key is returned.
324 |
# File 'lib/rbtree.rb', line 324 def nearest(key) = ((n = find_nearest_node(key)) == @nil_node)? nil : n.pair |
#nearest_key(key) ⇒ Object?
Returns the key with the key closest to the given key.
This method requires keys to be numeric or support subtraction and abs methods.
310 |
# File 'lib/rbtree.rb', line 310 def nearest_key(key) = ((n = find_nearest_node(key)) == @nil_node)? nil : n.key |
#pop ⇒ Array(Object, Object)?
Removes and returns the maximum key-value pair.
532 533 534 535 536 537 |
# File 'lib/rbtree.rb', line 532 def pop return nil unless (n = @max_node) != @nil_node pair = n.pair delete(n.key) pair end |
#prev(key) ⇒ Array(Object, Object)?
Returns the key-value pair with the largest key that is smaller than the given key.
If the key exists in the tree, returns the predecessor (previous element). If the key does not exist, returns the largest key-value pair with key < given key.
352 |
# File 'lib/rbtree.rb', line 352 def prev(key) = ((n = find_predecessor_node(key)) == @nil_node)? nil : n.pair |
#prev_key(key) ⇒ Object?
Returns the key with the largest key that is smaller than the given key.
If the key exists in the tree, returns the predecessor (previous element). If the key does not exist, returns the largest key with key < given key.
338 |
# File 'lib/rbtree.rb', line 338 def prev_key(key) = ((n = find_predecessor_node(key)) == @nil_node)? nil : n.key |
#reject {|key, value| ... } ⇒ RBTree, Enumerator
Returns a new tree containing key-value pairs for which the block returns false.
739 740 741 742 743 744 |
# File 'lib/rbtree.rb', line 739 def reject(&block) return enum_for(__method__) { size } unless block_given? result = new_derived_tree each { |k, v| result.insert(k, v) unless block.call(k, v) } result end |
#reject! {|key, value| ... } ⇒ RBTree, ...
Deletes key-value pairs for which the block returns true. Returns nil if no changes were made.
750 751 752 753 754 755 |
# File 'lib/rbtree.rb', line 750 def reject!(&block) return enum_for(__method__) { size } unless block_given? size_before = size delete_if(&block) size == size_before ? nil : self end |
#reverse_each(safe: false) {|key, value| ... } ⇒ Enumerator, RBTree
Iterates over all key-value pairs in descending order of keys.
Iterates over all key-value pairs in descending order of keys.
This is an alias for each(reverse: true).
630 631 632 633 |
# File 'lib/rbtree.rb', line 630 def reverse_each(safe: false, &block) return enum_for(__method__, safe: safe) { size } unless block_given? each(reverse: true, safe: safe, &block) end |
#select {|key, value| ... } ⇒ RBTree, Enumerator
Returns a new tree containing key-value pairs for which the block returns true.
728 729 730 731 732 733 |
# File 'lib/rbtree.rb', line 728 def select(&block) return enum_for(__method__) { size } unless block_given? result = new_derived_tree each { |k, v| result.insert(k, v) if block.call(k, v) } result end |
#shift ⇒ Array(Object, Object)?
Removes and returns the minimum key-value pair.
518 519 520 521 522 523 |
# File 'lib/rbtree.rb', line 518 def shift return nil unless (n = @min_node) != @nil_node pair = n.pair delete(n.key) pair end |
#size ⇒ Integer Also known as: value_count
Returns the number of key-value pairs stored in the tree.
170 |
# File 'lib/rbtree.rb', line 170 def size = @key_count |
#succ(key) ⇒ Array(Object, Object)?
Returns the key-value pair with the smallest key that is larger than the given key.
If the key exists in the tree, returns the successor (next element). If the key does not exist, returns the smallest key-value pair with key > given key.
380 |
# File 'lib/rbtree.rb', line 380 def succ(key) = ((n = find_successor_node(key)) == @nil_node)? nil : n.pair |
#succ_key(key) ⇒ Object?
Returns the key with the smallest key that is larger than the given key.
If the key exists in the tree, returns the successor (next element). If the key does not exist, returns the smallest key with key > given key.
366 |
# File 'lib/rbtree.rb', line 366 def succ_key(key) = ((n = find_successor_node(key)) == @nil_node)? nil : n.key |
#to_h ⇒ Hash
Returns a Hash containing all key-value pairs from the tree, in ascending key order.
157 158 159 160 161 |
# File 'lib/rbtree.rb', line 157 def to_h h = {} each { |k, v| h[k] = v } h end |
#valid? ⇒ Boolean
Validates the red-black tree properties and the auxiliary structures.
Checks that:
- Root is black and has no parent
- All paths from root to leaves have the same number of black nodes
- No red node has a red child
- Keys are ordered against bounds inherited from ancestors
- Every child's parent pointer points back at its parent
- The Hash index holds exactly one entry per node, mapped to that node
@min_node/@max_nodeare the actual extremes, andkey_countis right
813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 |
# File 'lib/rbtree.rb', line 813 def valid? return false if @root.color == Node::RED return false if @root != @nil_node && @root.parent != @nil_node return false if check_black_height(@root) == -1 return false unless check_order(@root, nil, nil) return false unless check_links(@root) count = 0 first_node = nil last_node = nil indexed = true each_node_asc do |n| count += 1 first_node ||= n last_node = n indexed &&= @hash_index[n.key].equal?(n) end return false unless indexed return false unless count == @key_count return false unless @hash_index.size == @key_count return false unless (first_node || @nil_node).equal?(@min_node) return false unless (last_node || @nil_node).equal?(@max_node) true end |
#value(key) ⇒ Object? Also known as: get
Retrieves the value associated with the given key.
269 |
# File 'lib/rbtree.rb', line 269 def value(key) = (@hash_index[key] || find_node_by_order(key))&.value |