class Containers::RubyRBTreeMap
A RBTreeMap is a map that is stored in sorted order based on the order of its keys. This ordering is determined by applying the function <=> to compare the keys. No duplicate values for keys are allowed, so duplicate values are overwritten.
A major advantage of RBTreeMap over a Hash is the fact that keys are stored in order and can thus be iterated over in order. This is useful for many datasets.
The implementation is adapted from Robert Sedgewick's Left Leaning Red-Black Tree implementation, which can be found at www.cs.princeton.edu/~rs/talks/LLRB/Java/RedBlackBST.java
Containers::RBTreeMap
automatically uses the faster C implementation if it was built when the gem was installed. Alternatively, Containers::RubyRBTreeMap
and Containers::CRBTreeMap
can be explicitly used as well; their functionality is identical.
Most methods have O(log n) complexity.
Attributes
Public Class Methods
Create and initialize a new empty TreeMap.
# File lib/containers/rb_tree_map.rb 26 def initialize 27 @root = nil 28 @height_black = 0 29 end
Public Instance Methods
Deletes the item and key if it's found, and returns the item. Returns nil if key is not present.
!!! Warning !!! There is a currently a bug in the delete method that occurs rarely but often enough, especially in large datasets. It is currently under investigation.
Complexity: O(log n)
map = Containers::TreeMap.new map.push("MA", "Massachusetts") map.push("GA", "Georgia") map.min_key #=> "GA"
# File lib/containers/rb_tree_map.rb 130 def delete(key) 131 result = nil 132 if @root 133 @root, result = delete_recursive(@root, key) 134 @root.color = :black if @root 135 end 136 result 137 end
Deletes the item with the smallest key and returns the item. Returns nil if key is not present.
Complexity: O(log n)
map = Containers::TreeMap.new map.push("MA", "Massachusetts") map.push("GA", "Georgia") map.delete_max #=> "Georgia" map.size #=> 1
# File lib/containers/rb_tree_map.rb 173 def delete_max 174 result = nil 175 if @root 176 @root, result = delete_max_recursive(@root) 177 @root.color = :black if @root 178 end 179 result 180 end
Deletes the item with the smallest key and returns the item. Returns nil if key is not present.
Complexity: O(log n)
map = Containers::TreeMap.new map.push("MA", "Massachusetts") map.push("GA", "Georgia") map.delete_min #=> "Massachusetts" map.size #=> 1
# File lib/containers/rb_tree_map.rb 154 def delete_min 155 result = nil 156 if @root 157 @root, result = delete_min_recursive(@root) 158 @root.color = :black if @root 159 end 160 result 161 end
Iterates over the TreeMap from smallest to largest element. Iterative approach.
# File lib/containers/rb_tree_map.rb 183 def each 184 return nil unless @root 185 stack = Containers::Stack.new 186 cursor = @root 187 loop do 188 if cursor 189 stack.push(cursor) 190 cursor = cursor.left 191 else 192 unless stack.empty? 193 cursor = stack.pop 194 yield(cursor.key, cursor.value) 195 cursor = cursor.right 196 else 197 break 198 end 199 end 200 end 201 end
Returns true if the tree is empty, false otherwise
# File lib/containers/rb_tree_map.rb 140 def empty? 141 @root.nil? 142 end
Return the item associated with the key, or nil if none found.
Complexity: O(log n)
map = Containers::TreeMap.new map.push("MA", "Massachusetts") map.push("GA", "Georgia") map.get("GA") #=> "Georgia"
# File lib/containers/rb_tree_map.rb 89 def get(key) 90 get_recursive(@root, key) 91 end
Return true if key is found in the TreeMap, false otherwise
Complexity: O(log n)
map = Containers::TreeMap.new map.push("MA", "Massachusetts") map.push("GA", "Georgia") map.has_key?("GA") #=> true map.has_key?("DE") #=> false
# File lib/containers/rb_tree_map.rb 77 def has_key?(key) 78 !get(key).nil? 79 end
Return the height of the tree structure in the TreeMap.
Complexity: O(1)
map = Containers::TreeMap.new map.push("MA", "Massachusetts") map.push("GA", "Georgia") map.height #=> 2
# File lib/containers/rb_tree_map.rb 64 def height 65 @root and @root.height or 0 66 end
Return the largest key in the map.
Complexity: O(log n)
map = Containers::TreeMap.new map.push("MA", "Massachusetts") map.push("GA", "Georgia") map.max_key #=> "MA"
# File lib/containers/rb_tree_map.rb 114 def max_key 115 @root.nil? ? nil : max_recursive(@root) 116 end
Return the smallest key in the map.
Complexity: O(log n)
map = Containers::TreeMap.new map.push("MA", "Massachusetts") map.push("GA", "Georgia") map.min_key #=> "GA"
# File lib/containers/rb_tree_map.rb 102 def min_key 103 @root.nil? ? nil : min_recursive(@root) 104 end
Insert an item with an associated key into the TreeMap, and returns the item inserted
Complexity: O(log n)
map = Containers::TreeMap.new map.push(“MA”, “Massachusetts”) #=> “Massachusetts” map.get(“MA”) #=> “Massachusetts”
# File lib/containers/rb_tree_map.rb 38 def push(key, value) 39 @root = insert(@root, key, value) 40 @height_black += 1 if isred(@root) 41 @root.color = :black 42 value 43 end
Return the number of items in the TreeMap.
map = Containers::TreeMap.new map.push("MA", "Massachusetts") map.push("GA", "Georgia") map.size #=> 2
# File lib/containers/rb_tree_map.rb 52 def size 53 @root and @root.size or 0 54 end
Private Instance Methods
# File lib/containers/rb_tree_map.rb 331 def delete_max_recursive(node) 332 if (isred(node.left)) 333 node = node.rotate_right 334 end 335 return nil, node.value if node.right.nil? 336 if ( !isred(node.right) && !isred(node.right.left) ) 337 node.move_red_right 338 end 339 node.right, result = delete_max_recursive(node.right) 340 341 return node.fixup, result 342 end
# File lib/containers/rb_tree_map.rb 318 def delete_min_recursive(node) 319 if node.left.nil? 320 return nil, node.value 321 end 322 if ( !isred(node.left) && !isred(node.left.left) ) 323 node.move_red_left 324 end 325 node.left, result = delete_min_recursive(node.left) 326 327 return node.fixup, result 328 end
# File lib/containers/rb_tree_map.rb 293 def delete_recursive(node, key) 294 if (key <=> node.key) == -1 295 node.move_red_left if ( !isred(node.left) && !isred(node.left.left) ) 296 node.left, result = delete_recursive(node.left, key) 297 else 298 node.rotate_right if isred(node.left) 299 if ( ( (key <=> node.key) == 0) && node.right.nil? ) 300 return nil, node.value 301 end 302 if ( !isred(node.right) && !isred(node.right.left) ) 303 node.move_red_right 304 end 305 if (key <=> node.key) == 0 306 result = node.value 307 node.value = get_recursive(node.right, min_recursive(node.right)) 308 node.key = min_recursive(node.right) 309 node.right = delete_min_recursive(node.right).first 310 else 311 node.right, result = delete_recursive(node.right, key) 312 end 313 end 314 return node.fixup, result 315 end
# File lib/containers/rb_tree_map.rb 345 def get_recursive(node, key) 346 return nil if node.nil? 347 case key <=> node.key 348 when 0 then return node.value 349 when -1 then return get_recursive(node.left, key) 350 when 1 then return get_recursive(node.right, key) 351 end 352 end
# File lib/containers/rb_tree_map.rb 369 def insert(node, key, value) 370 return Node.new(key, value) unless node 371 372 case key <=> node.key 373 when 0 then node.value = value 374 when -1 then node.left = insert(node.left, key, value) 375 when 1 then node.right = insert(node.right, key, value) 376 end 377 378 node.rotate_left if (node.right && node.right.red?) 379 node.rotate_right if (node.left && node.left.red? && node.left.left && node.left.left.red?) 380 node.colorflip if (node.left && node.left.red? && node.right && node.right.red?) 381 node.update_size 382 end
# File lib/containers/rb_tree_map.rb 385 def isred(node) 386 return false if node.nil? 387 388 node.color == :red 389 end
# File lib/containers/rb_tree_map.rb 362 def max_recursive(node) 363 return node.key if node.right.nil? 364 365 max_recursive(node.right) 366 end
# File lib/containers/rb_tree_map.rb 355 def min_recursive(node) 356 return node.key if node.left.nil? 357 358 min_recursive(node.left) 359 end