datastructures 0.2.1 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README.md +118 -2
- data/lib/datastructures.rb +4 -1
- data/lib/datastructures/adjacency_list.rb +82 -0
- data/lib/datastructures/linked_list.rb +179 -0
- data/lib/datastructures/tree_node.rb +73 -0
- data/lib/datastructures/version.rb +2 -2
- data/test/benchmarks.rb +36 -0
- data/test/coverage/assets/0.7.1/application.css +1110 -0
- data/test/coverage/assets/0.7.1/application.js +626 -0
- data/test/coverage/assets/0.7.1/fancybox/blank.gif +0 -0
- data/test/coverage/assets/0.7.1/fancybox/fancy_close.png +0 -0
- data/test/coverage/assets/0.7.1/fancybox/fancy_loading.png +0 -0
- data/test/coverage/assets/0.7.1/fancybox/fancy_nav_left.png +0 -0
- data/test/coverage/assets/0.7.1/fancybox/fancy_nav_right.png +0 -0
- data/test/coverage/assets/0.7.1/fancybox/fancy_shadow_e.png +0 -0
- data/test/coverage/assets/0.7.1/fancybox/fancy_shadow_n.png +0 -0
- data/test/coverage/assets/0.7.1/fancybox/fancy_shadow_ne.png +0 -0
- data/test/coverage/assets/0.7.1/fancybox/fancy_shadow_nw.png +0 -0
- data/test/coverage/assets/0.7.1/fancybox/fancy_shadow_s.png +0 -0
- data/test/coverage/assets/0.7.1/fancybox/fancy_shadow_se.png +0 -0
- data/test/coverage/assets/0.7.1/fancybox/fancy_shadow_sw.png +0 -0
- data/test/coverage/assets/0.7.1/fancybox/fancy_shadow_w.png +0 -0
- data/test/coverage/assets/0.7.1/fancybox/fancy_title_left.png +0 -0
- data/test/coverage/assets/0.7.1/fancybox/fancy_title_main.png +0 -0
- data/test/coverage/assets/0.7.1/fancybox/fancy_title_over.png +0 -0
- data/test/coverage/assets/0.7.1/fancybox/fancy_title_right.png +0 -0
- data/test/coverage/assets/0.7.1/fancybox/fancybox-x.png +0 -0
- data/test/coverage/assets/0.7.1/fancybox/fancybox-y.png +0 -0
- data/test/coverage/assets/0.7.1/fancybox/fancybox.png +0 -0
- data/test/coverage/assets/0.7.1/favicon_green.png +0 -0
- data/test/coverage/assets/0.7.1/favicon_red.png +0 -0
- data/test/coverage/assets/0.7.1/favicon_yellow.png +0 -0
- data/test/coverage/assets/0.7.1/loading.gif +0 -0
- data/test/coverage/assets/0.7.1/magnify.png +0 -0
- data/test/coverage/assets/0.7.1/smoothness/images/ui-bg_flat_0_aaaaaa_40x100.png +0 -0
- data/test/coverage/assets/0.7.1/smoothness/images/ui-bg_flat_75_ffffff_40x100.png +0 -0
- data/test/coverage/assets/0.7.1/smoothness/images/ui-bg_glass_55_fbf9ee_1x400.png +0 -0
- data/test/coverage/assets/0.7.1/smoothness/images/ui-bg_glass_65_ffffff_1x400.png +0 -0
- data/test/coverage/assets/0.7.1/smoothness/images/ui-bg_glass_75_dadada_1x400.png +0 -0
- data/test/coverage/assets/0.7.1/smoothness/images/ui-bg_glass_75_e6e6e6_1x400.png +0 -0
- data/test/coverage/assets/0.7.1/smoothness/images/ui-bg_glass_95_fef1ec_1x400.png +0 -0
- data/test/coverage/assets/0.7.1/smoothness/images/ui-bg_highlight-soft_75_cccccc_1x100.png +0 -0
- data/test/coverage/assets/0.7.1/smoothness/images/ui-icons_222222_256x240.png +0 -0
- data/test/coverage/assets/0.7.1/smoothness/images/ui-icons_2e83ff_256x240.png +0 -0
- data/test/coverage/assets/0.7.1/smoothness/images/ui-icons_454545_256x240.png +0 -0
- data/test/coverage/assets/0.7.1/smoothness/images/ui-icons_888888_256x240.png +0 -0
- data/test/coverage/assets/0.7.1/smoothness/images/ui-icons_cd0a0a_256x240.png +0 -0
- data/test/coverage/index.html +72 -0
- data/test/test_adjacency_list.rb +79 -0
- data/test/test_datastructures.rb +5 -1
- data/test/test_linked_list.rb +96 -0
- data/test/test_stack.rb +1 -1
- data/test/test_tree.rb +77 -0
- metadata +68 -3
data/README.md
CHANGED
@@ -26,7 +26,7 @@ A queue is a simple container-based structure that mimics a real-life queue (e.g
|
|
26
26
|
Usage:
|
27
27
|
|
28
28
|
```ruby
|
29
|
-
require '
|
29
|
+
require 'datastructures'
|
30
30
|
queue = DataStructures::Queue.new
|
31
31
|
queue.enqueue('first')
|
32
32
|
queue.enqueue('second')
|
@@ -46,7 +46,7 @@ The stack is the sibling of the queue. It mimicks a real-life stack (e.g. of pap
|
|
46
46
|
Usage:
|
47
47
|
|
48
48
|
```ruby
|
49
|
-
require '
|
49
|
+
require 'datastructures'
|
50
50
|
stack = DataStructures::Stack.new
|
51
51
|
stack.push('first')
|
52
52
|
stack.push('second')
|
@@ -57,4 +57,120 @@ stack.bottom # => 'first'
|
|
57
57
|
stack.pop # => 'second'
|
58
58
|
stack.pop # => 'first'
|
59
59
|
stack.pop # => RuntimeError, "Stack underflow: nothing to pop"
|
60
|
+
```
|
61
|
+
|
62
|
+
## Day 3: Tree
|
63
|
+
|
64
|
+
A tree is a directed graph where any two nodes are connected by only one edge, and there is a specified 'root' node, away from which all edges are directed. For any edge, the node that it points from is the *parent*, and the node it points to is the *child*. This implementation is currently very crude, and I hope to expand it by:
|
65
|
+
|
66
|
+
- separating the node and tree classes
|
67
|
+
- including search and shortest path algorithms
|
68
|
+
- include more traversal algorithms
|
69
|
+
|
70
|
+
Currently the implementation offers the ability to construct a tree and traverse it manually using family methods (*parent*, *child*, *siblings*, *descendents*). Nodes can have associated data.
|
71
|
+
|
72
|
+
```ruby
|
73
|
+
require 'datastructures'
|
74
|
+
|
75
|
+
# start with a root TreeNode
|
76
|
+
tree = DataStructures::TreeNode.new('root node')
|
77
|
+
tree.is_root? # => true
|
78
|
+
tree.is_leaf? # => true
|
79
|
+
|
80
|
+
# children are also TreeNodes
|
81
|
+
child1 = DataStructures::TreeNode.new('child')
|
82
|
+
tree.add_child(child1)
|
83
|
+
tree.child_count # => 1
|
84
|
+
tree.add_child(DataStructures::TreeNode.new('another child'))
|
85
|
+
tree.child_count # => 2
|
86
|
+
tree.is_root? # => true
|
87
|
+
tree.is_leaf? # => false
|
88
|
+
child1.is_leaf? # => true
|
89
|
+
|
90
|
+
# we can traverse by querying the family
|
91
|
+
tree.siblings # => []
|
92
|
+
child1.siblings.map{ |sibling| sibling.data } # => ["another child"]
|
93
|
+
|
94
|
+
child1.parent == tree # => true
|
95
|
+
child1.parent == child.siblings.first.parent # => true
|
96
|
+
|
97
|
+
tree.descendents.map { |d| d.data } # => ["child", "another child"]
|
98
|
+
```
|
99
|
+
|
100
|
+
## Day 4: Linked List
|
101
|
+
|
102
|
+
A linked list is a group of items which are ordered, and where the ordering is determined solely by the information each item contains about its neighbours.
|
103
|
+
|
104
|
+
This implementation is a doubly-linked list, which means that each item retains a reference to the *next* and *previous* items in the list.
|
105
|
+
|
106
|
+
The advantage of a linked list over a traditional array is that elements can be inserted and deleted efficiently.
|
107
|
+
|
108
|
+
```ruby
|
109
|
+
ll = DataStructures::LinkedList.new('one')
|
110
|
+
ll.first.data # => 'one'
|
111
|
+
ll[0] # => 'one'
|
112
|
+
ll << 'two' # => ["one", "two"]
|
113
|
+
ll.size # => 2
|
114
|
+
ll.length # => 2
|
115
|
+
ll.last.data # => 'two'
|
116
|
+
ll[ll.size - 1] # => 'two'
|
117
|
+
|
118
|
+
# linked lists can act as stacks
|
119
|
+
ll.push 'three' # => ["one", "two", "three"]
|
120
|
+
ll.size # => 3
|
121
|
+
ll.pop # => "three"
|
122
|
+
ll.size # => 2
|
123
|
+
puts ll # => ["one", "two"]
|
124
|
+
|
125
|
+
# or as queues
|
126
|
+
ll.push 'three' # => ["one", "two", "three"]
|
127
|
+
ll.shift # => 'one'
|
128
|
+
ll.size # => 2
|
129
|
+
ll.first.data 'two'
|
130
|
+
|
131
|
+
# we can insert and delete
|
132
|
+
ll.insert(1, 'one point five') # => ["two", "one point five", "three"]
|
133
|
+
ll.delete(1)
|
134
|
+
ll.to_s # => ['two', 'three']
|
135
|
+
```
|
136
|
+
|
137
|
+
## Day 5: Adjacency List
|
138
|
+
|
139
|
+
An adjacency list is a structure for representing a graph. Nodes are named; the name can be any hashable object. Data can be stored in nodes, but not edges. The graph can be traversed manually by querying the neighbours of a node.
|
140
|
+
|
141
|
+
The implementation is currently basic. I plan to improve it by:
|
142
|
+
|
143
|
+
* implementing depth- and breadth-first search
|
144
|
+
* implementing Dijkstra's algorithm for finding the shortest path between two nodes
|
145
|
+
* visualise the graph (maybe d3.js)
|
146
|
+
|
147
|
+
```ruby
|
148
|
+
require 'datastructures'
|
149
|
+
|
150
|
+
al = DataStructures::AdjacencyList.new
|
151
|
+
|
152
|
+
al.add('one', 1, [2])
|
153
|
+
al.add('two', 2, [3])
|
154
|
+
al.add('three', 3, [1])
|
155
|
+
al.add('four', 4, [2])
|
156
|
+
|
157
|
+
al.get_node_value(1) # => 'one'
|
158
|
+
al.set_node_value(1, 'new value')
|
159
|
+
|
160
|
+
al.neighbours(1) # => [2]
|
161
|
+
al.adjacent?(2, 3) # => true
|
162
|
+
al.adjacent?(1, 4) # => false
|
163
|
+
|
164
|
+
al.add_edge(1, 4)
|
165
|
+
al.adjacent?(1, 4) # => true
|
166
|
+
|
167
|
+
al.delete_edge(2, 3)
|
168
|
+
al.adjacent?(2, 3) # => false
|
169
|
+
|
170
|
+
al.to_s
|
171
|
+
# 1 (new value) => [2, 4]
|
172
|
+
# 2 (two) => []
|
173
|
+
# 3 (three) => [1]
|
174
|
+
# 4 (four) => [2]
|
175
|
+
|
60
176
|
```
|
data/lib/datastructures.rb
CHANGED
@@ -0,0 +1,82 @@
|
|
1
|
+
module DataStructures
|
2
|
+
|
3
|
+
# Implements an Adjacency list with indexed nodes
|
4
|
+
class AdjacencyList
|
5
|
+
|
6
|
+
ALNode = Struct.new(:value)
|
7
|
+
|
8
|
+
attr_accessor :edges
|
9
|
+
|
10
|
+
# Returns a new AdjacencyList
|
11
|
+
# Nodes are accessed with unique names if +:named+ is true,
|
12
|
+
# otherwise they are accessed with integer indices (default).
|
13
|
+
def initialize(named=false)
|
14
|
+
@nodes = {}
|
15
|
+
@edges = {}
|
16
|
+
end
|
17
|
+
|
18
|
+
# Assignment - adds a new node with +:value+, and
|
19
|
+
# +:nodeidentifier+, and optionally an array of
|
20
|
+
# identifiers of other nodes defining +:edges+.
|
21
|
+
# Returns self, so that assignments can be chained.
|
22
|
+
def add(value, nodeidentifier, edges=Array.new)
|
23
|
+
node = ALNode.new(value)
|
24
|
+
@nodes[nodeidentifier] = node
|
25
|
+
@edges[nodeidentifier] = edges
|
26
|
+
self
|
27
|
+
end
|
28
|
+
|
29
|
+
# Removal - deletes the node at +:nodeidentifier+, which should be
|
30
|
+
# an integer index if this is an indexed adjacency list, or the name
|
31
|
+
# of the node if this is a names adjacency list.
|
32
|
+
def delete(nodeidentifier)
|
33
|
+
node = @nodes[nodeidentifier]
|
34
|
+
@nodes[nodeidentifier] = nil
|
35
|
+
@edges.delete node
|
36
|
+
end
|
37
|
+
|
38
|
+
# Removal - deletes the edge(s) +:edges+ connected to the node
|
39
|
+
# referenced by +:nodeidentifer+.
|
40
|
+
def delete_edge(nodeidentifier, *edges)
|
41
|
+
alledges = @edges[nodeidentifier]
|
42
|
+
edges.each { |edge| alledges.delete edge }
|
43
|
+
end
|
44
|
+
|
45
|
+
# Returns the value of the node with +:nodeidentifier+
|
46
|
+
def get_node_value nodeidentifier
|
47
|
+
@nodes[nodeidentifier].value
|
48
|
+
end
|
49
|
+
|
50
|
+
# Set with value of node at +:nodeidentifier+ to +:value+
|
51
|
+
def set_node_value(nodeidentifier, value)
|
52
|
+
@nodes[nodeidentifier].value = value
|
53
|
+
end
|
54
|
+
|
55
|
+
# Adds an edge from node with identifier +:x+ to node
|
56
|
+
# with identifier +:y+.
|
57
|
+
def add_edge(x, y)
|
58
|
+
@edges[x] << y
|
59
|
+
end
|
60
|
+
|
61
|
+
# True if +:x+ and +:y+ are connected by an edge.
|
62
|
+
def adjacent?(x, y)
|
63
|
+
@edges[x].include?(y) || @edges[y].include?(x)
|
64
|
+
end
|
65
|
+
|
66
|
+
# Return an array of identifiers of all nodes connected to
|
67
|
+
# node at +:nodeidentifier+ by edges.
|
68
|
+
def neighbours nodeidentifier
|
69
|
+
@edges[nodeidentifier]
|
70
|
+
end
|
71
|
+
|
72
|
+
# Return a string representation of the graph
|
73
|
+
def to_s
|
74
|
+
s = ""
|
75
|
+
@nodes.each do |identifier, node|
|
76
|
+
s += "#{identifier} (#{node.value}) => #{@edges[identifier]} \n"
|
77
|
+
end
|
78
|
+
s
|
79
|
+
end
|
80
|
+
|
81
|
+
end
|
82
|
+
end
|
@@ -0,0 +1,179 @@
|
|
1
|
+
module DataStructures
|
2
|
+
# Implements a doubly Linked List.
|
3
|
+
class LinkedList
|
4
|
+
|
5
|
+
require 'pp'
|
6
|
+
|
7
|
+
LLNode = Struct.new(:data, :next, :previous)
|
8
|
+
|
9
|
+
attr_accessor :first
|
10
|
+
attr_accessor :last
|
11
|
+
attr_accessor :size
|
12
|
+
|
13
|
+
alias :length :size
|
14
|
+
|
15
|
+
# Returns a new LinkedList
|
16
|
+
#
|
17
|
+
# If no arguments are sent, the new LinkedList will be empty.
|
18
|
+
# When one or more objects are sent as arguments, the LinkedList
|
19
|
+
# is populated with those objects in the order sent.
|
20
|
+
def initialize *entries
|
21
|
+
@size = 0
|
22
|
+
unless entries.empty?
|
23
|
+
@first = LLNode.new(entries.shift, nil, nil)
|
24
|
+
@last = @first
|
25
|
+
@size = 1
|
26
|
+
self.push(*entries) unless entries.empty?
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
# Returns true if the LinkedList is empty
|
31
|
+
def empty?
|
32
|
+
@size == 0
|
33
|
+
end
|
34
|
+
|
35
|
+
# Element Reference - Returns the element at +index+
|
36
|
+
def [] index
|
37
|
+
current = @first
|
38
|
+
index.times do
|
39
|
+
current = current.next
|
40
|
+
end
|
41
|
+
current.data
|
42
|
+
end
|
43
|
+
|
44
|
+
# Element Assignment - Sets the element at +index+ to
|
45
|
+
# +:data+
|
46
|
+
def []= index, data
|
47
|
+
if index > @size - 1
|
48
|
+
# fill in the gaps
|
49
|
+
((index - @size) + 1).times do
|
50
|
+
self.push nil
|
51
|
+
end
|
52
|
+
@last.data = data
|
53
|
+
else
|
54
|
+
# replace existing value
|
55
|
+
current = @first
|
56
|
+
index.times do
|
57
|
+
current = current.next
|
58
|
+
end
|
59
|
+
current.data = data
|
60
|
+
end
|
61
|
+
self
|
62
|
+
end
|
63
|
+
|
64
|
+
# Insert a node with +:data+ at +:index+.
|
65
|
+
# All nodes +:index+ and above get moved along one.
|
66
|
+
def insert index, data
|
67
|
+
old_node = @first
|
68
|
+
index.times do
|
69
|
+
old_node = old_node.next
|
70
|
+
end
|
71
|
+
new_node = LLNode.new(data, old_node, old_node.previous)
|
72
|
+
old_node.previous.next = new_node
|
73
|
+
old_node.previous = new_node
|
74
|
+
self
|
75
|
+
end
|
76
|
+
|
77
|
+
# Delete the node at +:index+
|
78
|
+
def delete index
|
79
|
+
current = @first
|
80
|
+
index.times do
|
81
|
+
current = current.next
|
82
|
+
end
|
83
|
+
current.previous.next = current.next
|
84
|
+
current.next.previous = current.previous
|
85
|
+
end
|
86
|
+
|
87
|
+
# Calls the given block once for each element in +self+, passing
|
88
|
+
# that element as a parameter
|
89
|
+
def each &block
|
90
|
+
current = @first
|
91
|
+
@size.times do
|
92
|
+
yield current.data
|
93
|
+
current = current.next
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
# Append - Pushes the given object(s) on to the end of this
|
98
|
+
# Linked List. The expression returns the list itself, so several
|
99
|
+
# appends may be chained together. See also #pop for the opposite effect.
|
100
|
+
def push *elements
|
101
|
+
elements.each do |element|
|
102
|
+
node = LLNode.new(element, nil, @last)
|
103
|
+
@first = node if @first.nil?
|
104
|
+
@last.next = node unless @last.nil?
|
105
|
+
@last = node
|
106
|
+
@size += 1
|
107
|
+
end
|
108
|
+
self
|
109
|
+
end
|
110
|
+
|
111
|
+
alias :<< :push
|
112
|
+
|
113
|
+
# Removes the last element from +self+ and returns it.
|
114
|
+
# Raises an underflow error if empty.
|
115
|
+
def pop
|
116
|
+
raise "Linked List underflow: nothing to pop." if self.size == 0
|
117
|
+
last = @last
|
118
|
+
@last = @last.previous
|
119
|
+
@size -= 1
|
120
|
+
last.data
|
121
|
+
end
|
122
|
+
|
123
|
+
# Prepends objects to the front of +self+, moving other elements
|
124
|
+
# upwards. See also #shift for the opposite effect.
|
125
|
+
def unshift *elements
|
126
|
+
elements.each do |element|
|
127
|
+
node = LLNode.new(element, @first, nil)
|
128
|
+
@last = node if @last.nil?
|
129
|
+
@first.previous = node unless @first.nil?
|
130
|
+
@first = node
|
131
|
+
@size += 1
|
132
|
+
end
|
133
|
+
self
|
134
|
+
end
|
135
|
+
|
136
|
+
# Removes the first element of self and returns it (shifting all
|
137
|
+
# other elements down by one.
|
138
|
+
def shift
|
139
|
+
raise "Linked List underflow: nothing to shift." if self.size == 0
|
140
|
+
first = @first
|
141
|
+
@first = @first.next
|
142
|
+
@size -= 1
|
143
|
+
first.data
|
144
|
+
end
|
145
|
+
|
146
|
+
# Returns the first index equal to +data+ (using == comparison).
|
147
|
+
# Counts from the beginning of the list.
|
148
|
+
def index data
|
149
|
+
current = @first
|
150
|
+
i = 0
|
151
|
+
while !current.nil?
|
152
|
+
return i if current.data == data
|
153
|
+
current = current.next
|
154
|
+
i += 1
|
155
|
+
end
|
156
|
+
nil
|
157
|
+
end
|
158
|
+
|
159
|
+
# Returns an array containing the data from the nodes in the list
|
160
|
+
def to_a
|
161
|
+
current = @first
|
162
|
+
array = []
|
163
|
+
while !current.nil?
|
164
|
+
array << current.data
|
165
|
+
current = current.next
|
166
|
+
end
|
167
|
+
array
|
168
|
+
end
|
169
|
+
|
170
|
+
# Returns a string representation of the list
|
171
|
+
def to_s
|
172
|
+
self.to_a.to_s
|
173
|
+
end
|
174
|
+
|
175
|
+
end # LinkedList
|
176
|
+
|
177
|
+
end # Biopsy
|
178
|
+
|
179
|
+
ll = DataStructures::LinkedList.new(*[1,2,3])
|
@@ -0,0 +1,73 @@
|
|
1
|
+
module DataStructures
|
2
|
+
# Implements a Tree data structure. TreeNode represents a single node,
|
3
|
+
# and has methods for accessing parents, siblings and children.
|
4
|
+
class TreeNode
|
5
|
+
|
6
|
+
attr_accessor :children
|
7
|
+
attr_accessor :parent
|
8
|
+
attr_accessor :data
|
9
|
+
|
10
|
+
# new TreeNode object.
|
11
|
+
# +:data+ is the content of the node, can be any Ruby object
|
12
|
+
# +:parent+ optionally specify the parent node. Must be a TreeNode. Not specifying a parent makes this a root node.
|
13
|
+
def initialize(data,parent=nil)
|
14
|
+
@data = data
|
15
|
+
@parent = nil
|
16
|
+
raise "parent must be a TreeNode" unless @parent.nil? || @parent.class == TreeNode
|
17
|
+
self.clear
|
18
|
+
end
|
19
|
+
|
20
|
+
# add a child node.
|
21
|
+
#+:child+ the node to add as a child. must be a TreeNode
|
22
|
+
def add_child child
|
23
|
+
child.parent = self
|
24
|
+
@children << child
|
25
|
+
end
|
26
|
+
|
27
|
+
# remove a child node.
|
28
|
+
#+:child+ the child node to remove. must be a TreeNode
|
29
|
+
def remove_child! child
|
30
|
+
@children.delete child
|
31
|
+
end
|
32
|
+
|
33
|
+
alias :<< :add_child
|
34
|
+
|
35
|
+
# count the direct children of this node
|
36
|
+
def child_count
|
37
|
+
@children.size
|
38
|
+
end
|
39
|
+
|
40
|
+
# true if the node is a leaf, i.e. has no children
|
41
|
+
def is_leaf?
|
42
|
+
@children.empty?
|
43
|
+
end
|
44
|
+
|
45
|
+
alias :empty? :is_leaf?
|
46
|
+
|
47
|
+
# true if this node is root, i.e. has no parent
|
48
|
+
def is_root?
|
49
|
+
@parent.nil?
|
50
|
+
end
|
51
|
+
|
52
|
+
# return an array of the siblings of this node. Nil if root.
|
53
|
+
def siblings
|
54
|
+
if self.is_root?
|
55
|
+
nil
|
56
|
+
else
|
57
|
+
@parent.children.reject { |sibling| sibling.equal? self }
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
# return an array of all descendents
|
62
|
+
def descendents
|
63
|
+
@children.map { |child| [child, child.descendents] }.flatten
|
64
|
+
end
|
65
|
+
|
66
|
+
# remove all children
|
67
|
+
def clear
|
68
|
+
@children = Array.new
|
69
|
+
end
|
70
|
+
|
71
|
+
end # TreeNode
|
72
|
+
|
73
|
+
end # Biopsy
|