Class: Btree::Node
- Inherits:
-
Object
- Object
- Btree::Node
- Defined in:
- lib/btree/node.rb
Instance Method Summary collapse
- #add_child(node) ⇒ Object
- #children ⇒ Object
- #dump(level = 0) ⇒ Object
- #full? ⇒ Boolean
-
#initialize(degree) ⇒ Node
constructor
A new instance of Node.
- #insert(key, value) ⇒ Object
- #keys ⇒ Object
- #leaf? ⇒ Boolean
- #size ⇒ Object
- #split(child_idx) ⇒ Object
- #value_of(key) ⇒ Object
- #values ⇒ Object
-
#values_of(range) ⇒ Object
Values whose keys fall in the range, in key order.
Constructor Details
#initialize(degree) ⇒ Node
Returns a new instance of Node.
14 15 16 17 18 |
# File 'lib/btree/node.rb', line 14 def initialize(degree) @degree = degree @keys = [] @children = [] end |
Instance Method Details
#add_child(node) ⇒ Object
33 34 35 |
# File 'lib/btree/node.rb', line 33 def add_child(node) @children << node end |
#children ⇒ Object
37 38 39 |
# File 'lib/btree/node.rb', line 37 def children @children.dup.freeze end |
#dump(level = 0) ⇒ Object
20 21 22 23 24 25 26 27 28 29 30 31 |
# File 'lib/btree/node.rb', line 20 def dump(level = 0) @keys.each_with_index do |key, idx| puts "LEVEL: #{level} => #{key.first}: full? #{full?} leaf? #{leaf?} children: #{values.inspect}" if @children[idx] @children[idx].dump(level + 1) end end (@children[@keys.size..-1] || []).each do |c| c.dump(level+1) end nil end |
#full? ⇒ Boolean
49 50 51 |
# File 'lib/btree/node.rb', line 49 def full? size >= 2 * @degree - 1 end |
#insert(key, value) ⇒ Object
105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 |
# File 'lib/btree/node.rb', line 105 def insert(key, value) # The slot the key would occupy is also the slot it would already occupy if # it were present, so locating it and rejecting a duplicate are one step. # Checked at every node on the way down, not just at the leaf: a key that a # split has promoted into an internal node would otherwise be descended # past and inserted a second time, hiding one copy in a subtree. i = key_index(key) raise "Duplicate key" if i < size && @keys[i].first == key if leaf? @keys.insert(i, [key, value]) else if @children[i] && @children[i].full? split(i) # The split just promoted a key into this node, after the check above. raise "Duplicate key" if @keys[i].first == key i += 1 if key > @keys[i].first end @children[i].insert(key, value) end end |
#keys ⇒ Object
41 42 43 |
# File 'lib/btree/node.rb', line 41 def keys @keys.map(&:first).freeze end |
#leaf? ⇒ Boolean
53 54 55 |
# File 'lib/btree/node.rb', line 53 def leaf? @children.length == 0 end |
#size ⇒ Object
57 58 59 |
# File 'lib/btree/node.rb', line 57 def size @keys.size end |
#split(child_idx) ⇒ Object
127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 |
# File 'lib/btree/node.rb', line 127 def split(child_idx) raise "Invalid child index #{child_idx} in split, num_children = #{@children.size}" if child_idx < 0 || child_idx >= @children.size #puts "SPLIT1: #{self.inspect}" splitee = @children[child_idx] y = Btree::Node.new(@degree) z = Btree::Node.new(@degree) (@degree-1).times do |j| z._keys[j] = splitee._keys[j+@degree] y._keys[j] = splitee._keys[j] end if !splitee.leaf? @degree.times do |j| z._children[j] = splitee._children[j+@degree] y._children[j] = splitee._children[j] end end mid_val = splitee._keys[@degree-1] #puts "SPLIT2: #{self.inspect}" (@keys.size).downto(child_idx) do |j| @children[j+1] = @children[j] end @children[child_idx+1] = z @children[child_idx] = y #puts "SPLIT3: #{self.inspect}" (@keys.size - 1).downto(child_idx) do |j| @keys[j+1] = @keys[j] end #puts "SPLIT4: #{self.inspect}" @keys[child_idx] = mid_val #puts "SPLIT5: #{self.inspect}" end |
#value_of(key) ⇒ Object
90 91 92 93 94 95 96 97 98 99 100 101 102 103 |
# File 'lib/btree/node.rb', line 90 def value_of(key) return values_of(key) if key.kind_of? Range i = key_index(key) if i < size && key == @keys[i].first return @keys[i].last elsif leaf? return nil else return @children[i].value_of(key) end end |
#values ⇒ Object
45 46 47 |
# File 'lib/btree/node.rb', line 45 def values @keys.map(&:last).freeze end |
#values_of(range) ⇒ Object
Values whose keys fall in the range, in key order. Subtrees that cannot contain an in-range key are never visited.
63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 |
# File 'lib/btree/node.rb', line 63 def values_of(range) result = Array.new lo = range.begin hi = range.end # Skip the keys, and the subtrees between them, that sort entirely below # the range. When every key is below it, this lands on the rightmost # child, which may still hold in-range keys. i = lo ? key_index(lo) : 0 result += @children[i].values_of(range) if !leaf? && @children[i] while i < size key = @keys[i].first # Everything from here on sorts above the range. break if hi && (range.exclude_end? ? key >= hi : key > hi) result << @keys[i].last if range.cover? key result += @children[i+1].values_of(range) if !leaf? && @children[i+1] i += 1 end result end |