-
Notifications
You must be signed in to change notification settings - Fork 6
/
Copy pathsimple_tree.rb
161 lines (132 loc) · 3.07 KB
/
simple_tree.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
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
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
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
#
# Ruby Tree Interface by Jason M. Adams. Distributed under the BSD license, please see LICENSE for more information.
#
# To use this interface, drop it in your current class with +include+.
# You must then simply implement the +parent+ and +children+ methods.
# * +parent+ returns the parent node of the current node or else nil if it's a root
# * +children+ returns an +Array+ of all children of this node or an empty +Array+ if it is a leaf node
#
module SimpleTree
def parent() raise "parent must be overridden"; end
def children() raise "children must be overridden"; end
#
# Return whether this node is a leaf node in the hierarchy.
#
def is_leaf?
if children.size == 0
true
else
false
end
end
#
# Determine whether this is the root node in the hierarchy.
#
def is_root?
if parent
false
else
true
end
end
#
# Determine whether the node has a parent.
#
def has_parent?
not is_root?
end
#
# Determine whether the node has children.
#
def has_children?
not is_leaf?
end
#
# Return the height of this subtree. A single node has height 1.
#
def height
heights = children.map {|child| child.height}
return 1 if heights.size == 0
return heights.max + 1
end
#
# Return an array containing the siblings of the current node.
#
def siblings
# handle case where this is the root node
return Array.new unless parent
sibs = Array.new
parent.children.each do |child|
next if child.id == self.id
sibs << child
end
sibs
end
#
# Return every node descending from this node's parent (except this node).
# This include all of the node's descendants.
#
def family
if parent
fam = [parent] + parent.descendants
else
fam = descendants
end
fam.delete(self)
fam
end
#
# Return an array containing every descendant of the current node.
#
def descendants
d = Array.new
children.each do |child|
d << child
d << child.descendants
end
d.flatten
end
#
# Return the grandparent of this node.
#
def grandparent
parent.parent if parent # returns nil by default if no parent
end
#
# Return all the leaf nodes having the current node as an ancestor.
#
def leaves
outp = Array.new
children.each do |child|
if child.is_leaf?
outp << child
else
outp << child.leaves
end
end
outp.flatten
end
#
# Helper method for to_s, returns a tree representation of the subtree
# rooted at this node. This assumes some sort of identifier is specified
# for the object being called (self.name, self.identifier, etc)
#
def tree_rep(depth=0)
if self.name
ident = self.name
elsif self.identifier
ident = self.identifier
else
ident = self.object_id
end
if depth > 0
outp = " #{([" "] * (depth - 1)).join("|")}\\- #{ident}\n"
else
outp = "#{ident}\n"
end
children.each do |child|
outp += child.tree_rep(depth + 1)
end
outp
end
end