lib/compsci/node.rb in compsci-0.1.1.1 vs lib/compsci/node.rb in compsci-0.2.0.1
- old
+ new
@@ -1,49 +1,78 @@
module CompSci
- # has a value and an array of children
+ # has a value and an array of children; allows child gaps
class Node
attr_accessor :value
attr_reader :children
- def initialize(value)
+ def initialize(value, children: [])
@value = value
- @children = []
+ if children.is_a?(Integer)
+ @children = Array.new(children)
+ else
+ @children = children
+ end
# @metadata = {}
end
- def add_child(node)
- @children << node
- end
-
- def new_child(value)
- self.add_child self.class.new(value)
- end
-
- def add_parent(node)
- node.add_child(self)
- end
-
def to_s
@value.to_s
end
+ # This could be done directly with self.children, but #set_child is part
+ # of the Node API.
+ def set_child(idx, node)
+ @children[idx] = node
+ end
+
def inspect
"#<%s:0x%0xi @value=%s @children=[%s]>" %
[self.class,
self.object_id,
self.to_s,
@children.map(&:to_s).join(', ')]
end
end
+ # adds a key to Node; often the key is used to place the node in the
+ # tree, independent of the value; e.g. key=priority, value=process_id
+ class KeyNode < Node
+ attr_accessor :key
+
+ def initialize(val, key: nil, children: [])
+ @key = key
+ super(val, children: children)
+ end
+
+ def to_s
+ [key, value].join(':')
+ end
+ end
+
+ # accumulate children; no child gaps
+ class FlexNode < Node
+ def add_child(node)
+ @children << node
+ end
+
+ # TODO: are we passing everything needed to self.class.new ?
+ def new_child(value)
+ self.add_child self.class.new(value)
+ end
+
+ def add_parent(node)
+ node.add_child(self)
+ end
+ end
+
# like Node but with a reference to its parent
class ChildNode < Node
attr_accessor :parent
- def initialize(value)
+ def initialize(value, children: [])
@parent = nil
- super(value)
+ super(value, children: children)
end
# O(log n) recursive
def gen
@parent ? @parent.gen + 1 : 0
@@ -51,17 +80,35 @@
def siblings
@parent ? @parent.children : []
end
+ def set_child(idx, node)
+ node.parent ||= self
+ raise "node has a parent: #{node.parent}" if node.parent != self
+ @children[idx] = node
+ end
+
+ def set_parent(idx, node)
+ @parent = node
+ @parent.set_child(idx, self)
+ end
+ end
+
+ # ChildNode which accumulates children with no gaps
+ class ChildFlexNode < ChildNode
def add_child(node)
node.parent ||= self
raise "node has a parent: #{node.parent}" if node.parent != self
- super(node)
+ @children << node
end
+ def new_child(value)
+ self.add_child self.class.new(value)
+ end
+
def add_parent(node)
@parent = node
- super(node)
+ @parent.add_child(self)
end
end
end