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

height_black[RW]

Public Class Methods

new() click to toggle source

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

[](key)
Alias for: get
[]=(key, value)
Alias for: push
delete(key) click to toggle source

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
delete_max() click to toggle source

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
delete_min() click to toggle source

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
each() { |key, value| ... } click to toggle source

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
empty?() click to toggle source

Returns true if the tree is empty, false otherwise

    # File lib/containers/rb_tree_map.rb
140 def empty?
141   @root.nil?
142 end
get(key) click to toggle source

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
Also aliased as: []
has_key?(key) click to toggle source

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
height() click to toggle source

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
max_key() click to toggle source

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
min_key() click to toggle source

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
push(key, value) click to toggle source

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
Also aliased as: []=
size() click to toggle source

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

delete_max_recursive(node) click to toggle source
    # 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
delete_min_recursive(node) click to toggle source
    # 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
delete_recursive(node, key) click to toggle source
    # 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
get_recursive(node, key) click to toggle source
    # 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
insert(node, key, value) click to toggle source
    # 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
isred(node) click to toggle source
    # File lib/containers/rb_tree_map.rb
385 def isred(node)
386   return false if node.nil?
387   
388   node.color == :red
389 end
max_recursive(node) click to toggle source
    # 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
min_recursive(node) click to toggle source
    # 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