Class: Tree::RedBlack
- Inherits:
-
Object
- Object
- Tree::RedBlack
- Includes:
- Enumerable
- Defined in:
- lib/tree/red_black.rb,
lib/tree/red_black/version.rb
Overview
Tree::RedBlack is a pure-Ruby implementation of a Red-Black tree – i.e., a self-balancing binary search tree with O(log n) search, insert and delete operations. It is appropriate for maintaining an ordered collection where insertion and deletion are desired at arbitrary positions.
The implementation differs slightly from the Wikipedia description referenced above. In particular, leaf nodes are nil
, which affects the details of node deletion.
Constant Summary collapse
- VERSION =
'0.4.3'
Instance Attribute Summary collapse
-
#allow_duplicates ⇒ Object
Returns the value of attribute allow_duplicates.
-
#root ⇒ Object
Returns the value of attribute root.
-
#size ⇒ Object
Returns the value of attribute size.
Instance Method Summary collapse
- #allow_duplicates? ⇒ Boolean
-
#bsearch(&block) ⇒ Object
Returns a Red-Black tree node satisfying a criterion defined in
block
by binary search. -
#delete(*values) ⇒ Object
Deletes a value or sequence of values from a Red-Black tree.
-
#dup ⇒ Object
Returns a deep copy of a Red-Black tree, provided that the
dup
method for values in the tree is also a deep copy. -
#in_order(&block) ⇒ Object
(also: #each)
Returns an enumerator for nodes in a Red-Black tree by in-order traversal.
-
#initialize(allow_duplicates = true) ⇒ RedBlack
constructor
Returns a new, empty Red-Black tree.
-
#insert(*values) ⇒ Object
Inserts a value or sequence of values in a Red-Black tree and increments the
size
attribute by the number of values inserted. -
#pre_order(&block) ⇒ Object
Returns an enumerator for nodes in a Red-Black tree by pre-order traversal.
-
#search(value, ifnone = nil) ⇒ Object
Returns a Red-Black tree node whose
key
matchesvalue
by binary search.
Constructor Details
#initialize(allow_duplicates = true) ⇒ RedBlack
Returns a new, empty Red-Black tree. If option allow_duplicates
is false
, then only unique values are inserted in a Red-Black tree.
The root
attribute references the root node of the tree. The size
attribute indicates the number of nodes in the tree. When size
is 0
, root
is always nil
.
Example
require 'tree/red_black'
rbt = Tree::RedBlack.new
p rbt.root #=> nil
p rbt.size #=> 0
p rbt.allow_duplicates? #=> true
43 44 45 46 47 |
# File 'lib/tree/red_black.rb', line 43 def initialize(allow_duplicates = true) @root = nil @size = 0 @allow_duplicates = allow_duplicates end |
Instance Attribute Details
#allow_duplicates ⇒ Object
Returns the value of attribute allow_duplicates.
24 25 26 |
# File 'lib/tree/red_black.rb', line 24 def allow_duplicates @allow_duplicates end |
#root ⇒ Object
Returns the value of attribute root.
24 25 26 |
# File 'lib/tree/red_black.rb', line 24 def root @root end |
#size ⇒ Object
Returns the value of attribute size.
24 25 26 |
# File 'lib/tree/red_black.rb', line 24 def size @size end |
Instance Method Details
#allow_duplicates? ⇒ Boolean
49 50 51 |
# File 'lib/tree/red_black.rb', line 49 def allow_duplicates? @allow_duplicates end |
#bsearch(&block) ⇒ Object
Returns a Red-Black tree node satisfying a criterion defined in block
by binary search.
If block
evaluates to true
or false
, returns the first node for which the block
evaluates to true
. In this case, the criterion is expected to return false
for nodes preceding the matching node and true
for subsequent nodes.
Example
require 'tree/red_black'
shuffled_values = [*1..10].shuffle
rbt = shuffled_values.reduce(Tree::RedBlack.new) do |acc, v|
acc.insert(v)
end
rbt.bsearch { |node| node.key >= 7 }
#=> <Tree::RedBlackNode:0x00... @key=7 ...>
If block
evaluates to <0
, 0
or >0
, returns first node for which block
evaluates to 0
. Otherwise returns nil
. In this case, the criterion is expected to return <0
for nodes preceding the matching node, 0
for some subsequent nodes and >0
for nodes beyond that.
Example
require 'tree/red_black'
shuffled_values = [*1..10].shuffle
rbt = shuffled_values.reduce(Tree::RedBlack.new) do |acc, v|
acc.insert(v)
end
rbt.bsearch { |node| 7 <=> node.key }
#=> <Tree::RedBlackNode:0x00... @key=7 ...>
If block+
is not given, returns an enumerator.
174 175 176 177 178 |
# File 'lib/tree/red_black.rb', line 174 def bsearch(&block) return enum_for(:bsearch) unless block_given? root ? root.bsearch(&block) : nil end |
#delete(*values) ⇒ Object
107 108 109 110 111 112 113 114 115 116 117 |
# File 'lib/tree/red_black.rb', line 107 def delete(*values) values.each do |value; new_root| new_root = root.nil? ? nil : root.delete_red_black(value) unless new_root.nil? @root = new_root @size -= 1 end @root = nil if size == 0 end self end |
#dup ⇒ Object
Returns a deep copy of a Red-Black tree, provided that the dup
method for values in the tree is also a deep copy.
Example
require 'tree/red_black'
rbt = Tree::RedBlack.new
rbt.insert({a: 1, b: 2})
rbt_copy = rbt.dup
p rbt.root.key #=> {:a=>1, :b=>2}
p rbt.root.key.delete(:a) #=> 1
p rbt.root.key #=> {:b=>2}
p rbt_copy.root.key #=> {:a=>1, :b=>2}
233 234 235 236 237 238 239 |
# File 'lib/tree/red_black.rb', line 233 def dup copy = RedBlack.new copy.size = size copy.allow_duplicates = allow_duplicates copy.root = root.dup copy end |
#in_order(&block) ⇒ Object Also known as: each
210 211 212 213 214 215 |
# File 'lib/tree/red_black.rb', line 210 def in_order(&block) return enum_for(:in_order) unless block_given? return if root.nil? root.in_order(&block) end |
#insert(*values) ⇒ Object
Inserts a value or sequence of values in a Red-Black tree and increments the size
attribute by the number of values inserted.
Since a Red-Black tree maintains an ordered, Enumerable collection, every value inserted must be comparable with every other value. Methods each
, map
, select
, find
, sort
, etc., can be applied directly to the tree.
The individual nodes yielded by enumeration respond to method key
to retrieve the value stored in that node. Method each
, in particular, is aliased to in_order
, so that nodes are sorted in ascending order by key
value. Nodes can also be traversed by method pre_order
, e.g., to generate paths in the tree.
Example
require 'tree/red_black'
rbt = Tree::RedBlack.new
rbt.insert(*1..10) #=> #<Tree::RedBlack:0x00...>
p rbt.size #=> 10
rbt.map(&:key) #=> [1, 2, ..., 10]
rbt.select { |node| node.key % 2 == 0 }.map(&:key)
#=> [2, 4, ..., 10]
81 82 83 84 85 86 87 88 89 90 91 |
# File 'lib/tree/red_black.rb', line 81 def insert(*values) values.each do |value; new_root| new_root = (root.nil? ? RedBlackNode.new(value, :BLACK) : root.insert_red_black(value, @allow_duplicates)) unless new_root.nil? @root = new_root @size += 1 end end self end |
#pre_order(&block) ⇒ Object
191 192 193 194 195 196 |
# File 'lib/tree/red_black.rb', line 191 def pre_order(&block) return enum_for(:pre_order) unless block_given? return if root.nil? root.pre_order(&block) end |
#search(value, ifnone = nil) ⇒ Object
Returns a Red-Black tree node whose key
matches value
by binary search. If no match is found, calls non-nil ifnone
, otherwise returns nil
.
Example
require 'tree/red_black'
shuffled_values = [*1..10].shuffle
rbt = shuffled_values.reduce(Tree::RedBlack.new) do |acc, v|
acc.insert(v)
end
rbt.search(7) #=> <Tree::RedBlackNode:0x00..., @key=7, ...>
133 134 135 |
# File 'lib/tree/red_black.rb', line 133 def search(value, ifnone = nil) root ? root.search(value, ifnone) : nil end |