albizia 0.0.1
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/Gemfile +11 -0
- data/Guardfile +6 -0
- data/README.md +5 -0
- data/Rakefile +0 -0
- data/lib/albizia.rb +2 -0
- data/lib/albizia/node.rb +209 -0
- data/lib/albizia/rb_node.rb +5 -0
- data/lib/albizia/tree.rb +16 -0
- data/spec/albizia/node_spec.rb +367 -0
- data/spec/albizia/rb_node_spec.rb +7 -0
- data/spec/spec_helper.rb +1 -0
- metadata +55 -0
data/Gemfile
ADDED
data/Guardfile
ADDED
data/README.md
ADDED
data/Rakefile
ADDED
File without changes
|
data/lib/albizia.rb
ADDED
data/lib/albizia/node.rb
ADDED
@@ -0,0 +1,209 @@
|
|
1
|
+
|
2
|
+
module Albizia
|
3
|
+
class Node
|
4
|
+
|
5
|
+
attr_accessor :left_child, :right_child, :value, :parent
|
6
|
+
|
7
|
+
def initialize(v=nil)
|
8
|
+
@value = v
|
9
|
+
@parent = nil
|
10
|
+
end
|
11
|
+
|
12
|
+
def empty?
|
13
|
+
leaf? && @value.nil?
|
14
|
+
end
|
15
|
+
|
16
|
+
# A leaf node has no children
|
17
|
+
def leaf?
|
18
|
+
@left_child.nil? && @right_child.nil?
|
19
|
+
end
|
20
|
+
|
21
|
+
# A root has no parent
|
22
|
+
def root?
|
23
|
+
@parent.nil?
|
24
|
+
end
|
25
|
+
|
26
|
+
# Return the root element of the tree
|
27
|
+
def root
|
28
|
+
root? ? self : @parent.root
|
29
|
+
end
|
30
|
+
|
31
|
+
# The depth of a node n is the length of the path from the root to the node.
|
32
|
+
# The set of all nodes at a given depth is sometimes called a level of the
|
33
|
+
# tree. The root node is at depth zero.
|
34
|
+
def depth
|
35
|
+
root? ? 0 : 1 + parent.depth
|
36
|
+
end
|
37
|
+
|
38
|
+
# The height of a tree is the length of the path from the root to the
|
39
|
+
# deepest node in the tree. A (rooted) tree with only one node (the root)
|
40
|
+
# has a height of zero.
|
41
|
+
#
|
42
|
+
# Available options :
|
43
|
+
# initial : this will mark the current node as a root.
|
44
|
+
#
|
45
|
+
def height(opts={})
|
46
|
+
if empty?
|
47
|
+
-1
|
48
|
+
elsif (root? && leaf?) || (opts[:initial] && leaf?)
|
49
|
+
0
|
50
|
+
elsif leaf?
|
51
|
+
1
|
52
|
+
else
|
53
|
+
current_height = (root? || opts[:initial]) ? 0 : 1
|
54
|
+
if @left_child.nil? && @right_child != nil
|
55
|
+
current_height + @right_child.height
|
56
|
+
elsif @left_child != nil && @right_child.nil?
|
57
|
+
current_height + @left_child.height
|
58
|
+
elsif @left_child != nil && @right_child != nil
|
59
|
+
current_height + [@left_child.height, @right_child.height].max
|
60
|
+
else
|
61
|
+
raise "Unhandled depth case"
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def >(other)
|
67
|
+
@value > other.value
|
68
|
+
end
|
69
|
+
|
70
|
+
def <(other)
|
71
|
+
@value < other.value
|
72
|
+
end
|
73
|
+
|
74
|
+
def <=>(other)
|
75
|
+
if @value < other.value
|
76
|
+
-1
|
77
|
+
elsif @value == other.value
|
78
|
+
0
|
79
|
+
else
|
80
|
+
1
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
# Siblings are nodes that share the same parent node.
|
85
|
+
def siblings
|
86
|
+
end
|
87
|
+
|
88
|
+
# All nodes above current node
|
89
|
+
def ancestors
|
90
|
+
end
|
91
|
+
|
92
|
+
# The size of a node is the number of descendants it has including itself.
|
93
|
+
def size
|
94
|
+
if leaf?
|
95
|
+
1
|
96
|
+
elsif @left_child.nil?
|
97
|
+
1 + @right_child.size
|
98
|
+
elsif @right_child.nil?
|
99
|
+
1 + @left_child.size
|
100
|
+
else
|
101
|
+
1 + @left_child.size + @right_child.size
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
# A tree is full if every nodes except leaves has 2 children
|
106
|
+
def full?
|
107
|
+
end
|
108
|
+
|
109
|
+
def balanced?
|
110
|
+
end
|
111
|
+
|
112
|
+
def degenerated?
|
113
|
+
end
|
114
|
+
|
115
|
+
# Return the highest value in the tree
|
116
|
+
def max
|
117
|
+
if @right_child.nil?
|
118
|
+
if empty?
|
119
|
+
nil
|
120
|
+
else
|
121
|
+
self
|
122
|
+
end
|
123
|
+
else
|
124
|
+
@right_child.max
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
# Return the lowest value in the tree
|
129
|
+
def min
|
130
|
+
if @left_child.nil?
|
131
|
+
if empty?
|
132
|
+
nil
|
133
|
+
else
|
134
|
+
self
|
135
|
+
end
|
136
|
+
else
|
137
|
+
@left_child.min
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
# Add a node with value equals to v in the tree
|
142
|
+
def add(v)
|
143
|
+
if empty?
|
144
|
+
@value = v
|
145
|
+
elsif v > @value
|
146
|
+
if(@right_child.nil?)
|
147
|
+
node = Node.new(v).tap { |n| n.parent = self }
|
148
|
+
@right_child = node
|
149
|
+
# return node
|
150
|
+
else
|
151
|
+
@right_child.add(v)
|
152
|
+
end
|
153
|
+
else
|
154
|
+
if @left_child.nil?
|
155
|
+
node = Node.new(v).tap { |n| n.parent = self }
|
156
|
+
@left_child = node
|
157
|
+
# return node
|
158
|
+
else
|
159
|
+
@left_child.add(v)
|
160
|
+
end
|
161
|
+
end
|
162
|
+
end
|
163
|
+
alias_method :<<, :add
|
164
|
+
|
165
|
+
# Traverse the tree and returns the list of elements
|
166
|
+
# For the following tree :
|
167
|
+
#
|
168
|
+
# 5
|
169
|
+
# / \
|
170
|
+
# 2 10
|
171
|
+
# / \
|
172
|
+
# 6 12
|
173
|
+
#
|
174
|
+
# It return [2, 5, 6, 10, 12]
|
175
|
+
#
|
176
|
+
def to_a
|
177
|
+
|
178
|
+
end
|
179
|
+
|
180
|
+
# Traverse the tree and return elements in a hash:
|
181
|
+
# For the following tree :
|
182
|
+
#
|
183
|
+
# 5
|
184
|
+
# / \
|
185
|
+
# 2 10
|
186
|
+
# / \
|
187
|
+
# 6 12
|
188
|
+
#
|
189
|
+
# It returns { :"5" => { :"2" => nil, :"10" => { :"6" => nil, :"12" => nil } } }
|
190
|
+
#
|
191
|
+
def to_hash
|
192
|
+
|
193
|
+
end
|
194
|
+
|
195
|
+
# Draw the tree in the console
|
196
|
+
# example :
|
197
|
+
#
|
198
|
+
# 5
|
199
|
+
# / \
|
200
|
+
# 2 10
|
201
|
+
# / \
|
202
|
+
# 6 12
|
203
|
+
#
|
204
|
+
def draw
|
205
|
+
|
206
|
+
end
|
207
|
+
|
208
|
+
end #class
|
209
|
+
end #module
|
data/lib/albizia/tree.rb
ADDED
@@ -0,0 +1,367 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
module Albizia
|
4
|
+
describe Node do
|
5
|
+
describe "#init" do
|
6
|
+
context "Without params" do
|
7
|
+
subject { Node.new }
|
8
|
+
|
9
|
+
it { should be_empty }
|
10
|
+
|
11
|
+
it "should have a height of -1" do
|
12
|
+
subject.height.should == -1
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
context "With an integer param" do
|
17
|
+
subject { Node.new(@v) }
|
18
|
+
before(:each) { @v = 0 }
|
19
|
+
|
20
|
+
it { should_not be_empty }
|
21
|
+
it { should be_root }
|
22
|
+
it { should be_leaf }
|
23
|
+
|
24
|
+
it "should have length equals to 0" do
|
25
|
+
subject.height.should == 0
|
26
|
+
end
|
27
|
+
|
28
|
+
it "should have the assigned value" do
|
29
|
+
subject.value.should == @v
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
describe "#add" do
|
35
|
+
context "To an empty tree" do
|
36
|
+
subject { Node.new }
|
37
|
+
before(:each) { subject.add(5) }
|
38
|
+
|
39
|
+
it "should be inserted at the root" do
|
40
|
+
subject.value.should == 5
|
41
|
+
subject.parent.should be_nil
|
42
|
+
end
|
43
|
+
|
44
|
+
it { should be_leaf }
|
45
|
+
|
46
|
+
it "should have a height of 0" do
|
47
|
+
subject.height.should == 0
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
context "To an almost empty tree" do
|
52
|
+
subject { Node.new(5) }
|
53
|
+
|
54
|
+
context "A greater value than root's value" do
|
55
|
+
before(:each) do
|
56
|
+
subject.add(10)
|
57
|
+
end
|
58
|
+
|
59
|
+
it { should be_root }
|
60
|
+
it { should_not be_leaf }
|
61
|
+
|
62
|
+
it "should be inserted on the right" do
|
63
|
+
subject.right_child.should_not be_empty
|
64
|
+
subject.right_child.value.should == 10
|
65
|
+
subject.left_child.should be_nil
|
66
|
+
end
|
67
|
+
|
68
|
+
it "should have a height of 1" do
|
69
|
+
subject.should_not be_empty
|
70
|
+
subject.right_child.should_not be_nil
|
71
|
+
subject.right_child.should be_leaf
|
72
|
+
subject.left_child.should be_nil
|
73
|
+
|
74
|
+
subject.height.should == 1
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
context "A lower value than root's value" do
|
79
|
+
before(:each) do
|
80
|
+
subject.add(1)
|
81
|
+
end
|
82
|
+
|
83
|
+
it { should_not be_leaf }
|
84
|
+
|
85
|
+
it "should be inserted on the left" do
|
86
|
+
subject.left_child.should_not be_empty
|
87
|
+
subject.left_child.value.should == 1
|
88
|
+
subject.right_child.should be_nil
|
89
|
+
end
|
90
|
+
|
91
|
+
it "should have a height of 1" do
|
92
|
+
subject.height.should == 1
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
end
|
97
|
+
|
98
|
+
context "To a non empty tree" do
|
99
|
+
subject { Node.new(5) }
|
100
|
+
before(:each) do
|
101
|
+
subject.add(3)
|
102
|
+
subject.add(7)
|
103
|
+
end
|
104
|
+
|
105
|
+
context "A greater value than root's value" do
|
106
|
+
context "A greater value than the current max value" do
|
107
|
+
before(:each) do
|
108
|
+
subject.add(8)
|
109
|
+
end
|
110
|
+
|
111
|
+
it "should be inserted on the right of the current right'est' node" do
|
112
|
+
subject.right_child.right_child.value.should == 8
|
113
|
+
end
|
114
|
+
it "should be the max" do
|
115
|
+
subject.max.value.should == 8
|
116
|
+
end
|
117
|
+
it "should be a leaf" do
|
118
|
+
subject.right_child.right_child.should be_leaf
|
119
|
+
end
|
120
|
+
it "should have a height of 2" do
|
121
|
+
subject.height.should == 2
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
context "A lower value than the current max value but greater than root's" do
|
126
|
+
before(:each) do
|
127
|
+
subject.add(6)
|
128
|
+
end
|
129
|
+
|
130
|
+
it "should be inserted on the left of the current right'est' node" do
|
131
|
+
subject.right_child.left_child.value.should == 6
|
132
|
+
end
|
133
|
+
it "should be a leaf" do
|
134
|
+
subject.right_child.left_child.should be_leaf
|
135
|
+
end
|
136
|
+
it "should have a height of 2" do
|
137
|
+
subject.height.should == 2
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
end
|
142
|
+
|
143
|
+
context "A lower value than root's value" do
|
144
|
+
context "A lower value than current min" do
|
145
|
+
before(:each) do
|
146
|
+
subject.add(1)
|
147
|
+
end
|
148
|
+
it "should be inserted on the left of the current left'est' node " do
|
149
|
+
subject.left_child.left_child.value.should == 1
|
150
|
+
end
|
151
|
+
|
152
|
+
it "should be a leaf" do
|
153
|
+
subject.left_child.left_child.should be_leaf
|
154
|
+
end
|
155
|
+
|
156
|
+
it "should be the min" do
|
157
|
+
subject.min.value.should == 1
|
158
|
+
end
|
159
|
+
|
160
|
+
it "should have a height of 2" do
|
161
|
+
subject.height.should == 2
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
165
|
+
context "A greater value than current min but still lower than root's " do
|
166
|
+
before(:each) do
|
167
|
+
subject.add(4)
|
168
|
+
end
|
169
|
+
it "should be inserted on the right of the current left'est' node" do
|
170
|
+
subject.left_child.right_child.value.should == 4
|
171
|
+
end
|
172
|
+
it "should be a leaf" do
|
173
|
+
subject.left_child.right_child.should be_leaf
|
174
|
+
end
|
175
|
+
it "should have a height of 2" do
|
176
|
+
subject.height.should == 2
|
177
|
+
end
|
178
|
+
end
|
179
|
+
end
|
180
|
+
|
181
|
+
end
|
182
|
+
end
|
183
|
+
|
184
|
+
describe "#root" do
|
185
|
+
subject { Node.new 10 }
|
186
|
+
|
187
|
+
context "Empty tree" do
|
188
|
+
it "should return self" do
|
189
|
+
subject.root.should == subject
|
190
|
+
end
|
191
|
+
end
|
192
|
+
|
193
|
+
context "Tree with one element" do
|
194
|
+
before(:each) do
|
195
|
+
subject.parent = Node.new(20)
|
196
|
+
end
|
197
|
+
|
198
|
+
it "should return subject's parent" do
|
199
|
+
subject.root.should == subject.parent
|
200
|
+
end
|
201
|
+
end
|
202
|
+
|
203
|
+
context "Tree with more than one element" do
|
204
|
+
|
205
|
+
it "should return the same root for each descendant" do
|
206
|
+
5.times.map do |i|
|
207
|
+
node = subject.add(i)
|
208
|
+
node.root.should == subject
|
209
|
+
end
|
210
|
+
end
|
211
|
+
end
|
212
|
+
|
213
|
+
end
|
214
|
+
describe "#depth" do
|
215
|
+
context "Empty tree" do
|
216
|
+
subject { Node.new }
|
217
|
+
|
218
|
+
it "should have a depth of 0" do
|
219
|
+
subject.depth.should == 0
|
220
|
+
end
|
221
|
+
|
222
|
+
end
|
223
|
+
|
224
|
+
context "Not empty tree" do
|
225
|
+
subject do
|
226
|
+
parent = Node.new(10)
|
227
|
+
Node.new(4).tap {|n| n.parent = parent }
|
228
|
+
end
|
229
|
+
|
230
|
+
it "should have a depth of 1" do
|
231
|
+
subject.depth.should == 1
|
232
|
+
end
|
233
|
+
|
234
|
+
it "should have a depth of 2" do
|
235
|
+
subject.parent.parent = Node.new(20)
|
236
|
+
subject.depth.should == 2
|
237
|
+
end
|
238
|
+
|
239
|
+
it "should still have a depth of 2 after adding a child" do
|
240
|
+
subject.parent.parent = Node.new(20)
|
241
|
+
subject.add(2)
|
242
|
+
subject.depth.should == 2
|
243
|
+
end
|
244
|
+
end
|
245
|
+
end
|
246
|
+
|
247
|
+
describe "#height" do
|
248
|
+
context "Empty tree" do
|
249
|
+
subject { Node.new }
|
250
|
+
|
251
|
+
it "should have a height of -1" do
|
252
|
+
subject.height.should == -1
|
253
|
+
end
|
254
|
+
end
|
255
|
+
|
256
|
+
context "Tree with one element" do
|
257
|
+
subject { Node.new 10 }
|
258
|
+
|
259
|
+
it "should have a height of 0" do
|
260
|
+
subject.height.should == 0
|
261
|
+
end
|
262
|
+
end
|
263
|
+
|
264
|
+
context "Tree with more than one element" do
|
265
|
+
subject { Node.new(10).tap { |n| n.add 4 } }
|
266
|
+
|
267
|
+
context "Tree's root" do
|
268
|
+
it "should have a height of 1 after initialization" do
|
269
|
+
subject.height.should == 1
|
270
|
+
end
|
271
|
+
|
272
|
+
it "should have a height of 1 after adding a new element at the same depth" do
|
273
|
+
subject.add 15
|
274
|
+
subject.height.should == 1
|
275
|
+
end
|
276
|
+
|
277
|
+
it "should have a height of 2 after adding a child on the right" do
|
278
|
+
subject.add 15
|
279
|
+
subject.add 20
|
280
|
+
subject.height.should == 2
|
281
|
+
end
|
282
|
+
end
|
283
|
+
|
284
|
+
context "Nodes in a tree ('initial' option)" do
|
285
|
+
|
286
|
+
it "should return a height of 2 for the parent of a leaf's parent" do
|
287
|
+
subject.add 15
|
288
|
+
node = subject.add 20
|
289
|
+
subject.add 25
|
290
|
+
subject.add 30
|
291
|
+
|
292
|
+
node.should_not be_leaf
|
293
|
+
node.height(initial: true).should == 2
|
294
|
+
end
|
295
|
+
|
296
|
+
it "should return a height of 1 for the parent of a leaf" do
|
297
|
+
subject.add 15
|
298
|
+
node = subject.add 20
|
299
|
+
subject.add 30
|
300
|
+
|
301
|
+
node.should_not be_leaf
|
302
|
+
node.height(initial: true).should == 1
|
303
|
+
end
|
304
|
+
|
305
|
+
it "should return a height of 0 for a leaf" do
|
306
|
+
subject.add 15
|
307
|
+
subject.add 20
|
308
|
+
node = subject.add 30
|
309
|
+
|
310
|
+
node.should be_leaf
|
311
|
+
node.height(initial: true).should == 0
|
312
|
+
end
|
313
|
+
end
|
314
|
+
end
|
315
|
+
|
316
|
+
end
|
317
|
+
|
318
|
+
describe "#find" do
|
319
|
+
context "A value which is not present in the tree" do
|
320
|
+
it "should raise an Exception"
|
321
|
+
end
|
322
|
+
|
323
|
+
context "The minimum value of the tree" do
|
324
|
+
it "should return the correct value"
|
325
|
+
end
|
326
|
+
|
327
|
+
context "The maximum value of the tree" do
|
328
|
+
it "should return the correct value"
|
329
|
+
end
|
330
|
+
|
331
|
+
context "A value which is lower than the root's value" do
|
332
|
+
it "should return the correct value"
|
333
|
+
end
|
334
|
+
|
335
|
+
context "A value which is greater than the root" do
|
336
|
+
it "should return the correct value"
|
337
|
+
end
|
338
|
+
end
|
339
|
+
|
340
|
+
describe "#delete" do
|
341
|
+
context "The root value" do
|
342
|
+
it "should delete the value"
|
343
|
+
end
|
344
|
+
|
345
|
+
context "A value which is not present in the tree" do
|
346
|
+
it "should raise an Exception"
|
347
|
+
end
|
348
|
+
|
349
|
+
context "The minimum value of the tree" do
|
350
|
+
it "should delete the value"
|
351
|
+
end
|
352
|
+
|
353
|
+
context "The maximum value of the tree" do
|
354
|
+
it "should delete the value"
|
355
|
+
end
|
356
|
+
|
357
|
+
context "A value which is lower than the root's value" do
|
358
|
+
it "should delete the value"
|
359
|
+
end
|
360
|
+
|
361
|
+
context "A value which is greater than the root" do
|
362
|
+
it "should delete the value"
|
363
|
+
end
|
364
|
+
end
|
365
|
+
|
366
|
+
end
|
367
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "albizia"
|
metadata
ADDED
@@ -0,0 +1,55 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: albizia
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Pierre Jambet
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-09-29 00:00:00.000000000 Z
|
13
|
+
dependencies: []
|
14
|
+
description: A simple gem implementing different kind of tree structures
|
15
|
+
email: pierre.jambet@gmail.com
|
16
|
+
executables: []
|
17
|
+
extensions: []
|
18
|
+
extra_rdoc_files: []
|
19
|
+
files:
|
20
|
+
- lib/albizia/node.rb
|
21
|
+
- lib/albizia/rb_node.rb
|
22
|
+
- lib/albizia/tree.rb
|
23
|
+
- lib/albizia.rb
|
24
|
+
- spec/albizia/node_spec.rb
|
25
|
+
- spec/albizia/rb_node_spec.rb
|
26
|
+
- spec/spec_helper.rb
|
27
|
+
- Gemfile
|
28
|
+
- Guardfile
|
29
|
+
- Rakefile
|
30
|
+
- README.md
|
31
|
+
homepage: http://pjambet.github.com/albizia/
|
32
|
+
licenses: []
|
33
|
+
post_install_message:
|
34
|
+
rdoc_options: []
|
35
|
+
require_paths:
|
36
|
+
- lib
|
37
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
38
|
+
none: false
|
39
|
+
requirements:
|
40
|
+
- - ! '>='
|
41
|
+
- !ruby/object:Gem::Version
|
42
|
+
version: '0'
|
43
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
44
|
+
none: false
|
45
|
+
requirements:
|
46
|
+
- - ! '>='
|
47
|
+
- !ruby/object:Gem::Version
|
48
|
+
version: '0'
|
49
|
+
requirements: []
|
50
|
+
rubyforge_project:
|
51
|
+
rubygems_version: 1.8.24
|
52
|
+
signing_key:
|
53
|
+
specification_version: 3
|
54
|
+
summary: Albzia is a basic tree implemention
|
55
|
+
test_files: []
|