rooted_tree 0.2.0 → 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 5fb0517447c09795b818f9918deab292ff76b693
4
- data.tar.gz: 9828b9590b6a2e98df0d956e5c316bde85cc982b
3
+ metadata.gz: bf70759dc7a2bf845496a1eb2291a91a4a60e5e2
4
+ data.tar.gz: 6e7365e5d05e9f8daa1b34e5c726f0d2d8865d1b
5
5
  SHA512:
6
- metadata.gz: 2f4290bf9357d919e8d92da2724366a405080fddf4e91878b74849f003986de6eddc42a68bd8038fb57ce3afb5106eb23226d049a84f902e5f6b32d6d35e36ec
7
- data.tar.gz: 4aaddad4f3f6f8c7f5a771889dae2a9ea5c3f4c6568a8500eb0a2f8f36fc1ee16c2f7d6d240ec117507ed40f1997ac30e1fb46c8069e995b70f27b809c8269d0
6
+ metadata.gz: 10622361191c35e83775a11d129245eaebc2ce0b69f970e24195dd20bba065784a53a29295446c733d7bd3179b74302a29fe83fd5da6b48fbcfd8c573310db86
7
+ data.tar.gz: 1e9c114ae888537459a66f2c7b1f27212c2d20160c35a9e84c7a111916c14d20f6042feb585e6430e18cce600a79b0177b7cb0f932e59b26c6f020f8d3ef25f7
@@ -2,8 +2,12 @@
2
2
 
3
3
  # Node
4
4
  #
5
+ # Nodes are mutable by default, since creating anyting but simple leafs would
6
+ # otherwise be imposible. Calling #freeze on a node makes the entire subtree
7
+ # immutable. This is used by the Tree class which only operates on frozen node
8
+ # structures.
5
9
  #
6
- # The following is an example of a rooted tree of height 3.
10
+ # The following is an example of a rooted tree with maximum depth 2.
7
11
  #
8
12
  # r - r, a, b, c, and d are internal vertices
9
13
  # +--+---+ - vertices e, f, g, h, i, and j are leaves
@@ -18,9 +22,14 @@
18
22
 
19
23
  module RootedTree
20
24
  class Node
21
- attr_accessor :first_child, :last_child
25
+ include Enumerable
26
+
27
+ attr_accessor :first_child, :last_child, :degree
22
28
  attr_writer :next, :prev, :parent
23
- protected :next=, :prev=, :parent=, :first_child=, :last_child=
29
+
30
+ protected :next=, :prev=, :parent=, :first_child=, :last_child=, :degree=
31
+
32
+ alias arity degree
24
33
 
25
34
  def initialize
26
35
  @parent = nil
@@ -28,6 +37,7 @@ module RootedTree
28
37
  @prev = nil
29
38
  @first_child = nil
30
39
  @last_child = nil
40
+ @degree = 0
31
41
  end
32
42
 
33
43
  def initialize_copy(*)
@@ -49,7 +59,7 @@ module RootedTree
49
59
  # A node is a leaf if it has no children.
50
60
 
51
61
  def leaf?
52
- @first_child.nil?
62
+ @degree == 0
53
63
  end
54
64
 
55
65
  # Internal?
@@ -106,16 +116,24 @@ module RootedTree
106
116
  end
107
117
 
108
118
  alias level depth
119
+
120
+ # Max Depth
121
+ #
122
+ # Returns the maximum node depth under this node.
123
+
124
+ def max_depth offset = depth
125
+ return offset if leaf?
126
+
127
+ children.map {|c| c.max_depth offset + 1 }.max
128
+ end
109
129
 
110
- # Degree
130
+ # Max Degree
111
131
  #
112
- # Returns the number of children of the node.
132
+ # Returns the highest child count of the nodes in the subtree.
113
133
 
114
- def degree
115
- children.count
134
+ def max_degree
135
+ children.map(&:degree).push(degree).max
116
136
  end
117
-
118
- alias arity degree
119
137
 
120
138
  # Size
121
139
  #
@@ -167,6 +185,8 @@ module RootedTree
167
185
  node.next = @next
168
186
  node.prev = self
169
187
  node.parent = @parent
188
+ @parent.degree += 1
189
+
170
190
  if @next
171
191
  @next.prev = node
172
192
  else
@@ -185,6 +205,8 @@ module RootedTree
185
205
  node.next = self
186
206
  node.prev = @prev
187
207
  node.parent = @parent
208
+ @parent.degree += 1
209
+
188
210
  if @prev
189
211
  @prev.next = node
190
212
  else
@@ -192,6 +214,13 @@ module RootedTree
192
214
  end
193
215
  @prev = node
194
216
  end
217
+
218
+ private def add_child_to_leaf(child)
219
+ @first_child = @last_child = child
220
+ child.next = child.prev = nil
221
+ @degree = 1
222
+ child.parent = self
223
+ end
195
224
 
196
225
  # Append Child
197
226
  #
@@ -199,9 +228,7 @@ module RootedTree
199
228
 
200
229
  def append_child(child)
201
230
  if leaf?
202
- @first_child = @last_child = child
203
- child.next = child.prev = nil
204
- child.parent = self
231
+ add_child_to_leaf child
205
232
  else
206
233
  @last_child.append_sibling child
207
234
  end
@@ -214,9 +241,7 @@ module RootedTree
214
241
 
215
242
  def prepend_child(child)
216
243
  if leaf?
217
- @first_child = @last_child = child
218
- child.next = child.prev = nil
219
- child.parent = self
244
+ add_child_to_leaf child
220
245
  else
221
246
  @first_child.prepend_sibling child
222
247
  end
@@ -243,6 +268,7 @@ module RootedTree
243
268
  @prev.next = @next
244
269
  end
245
270
 
271
+ @parent.degree -= 1
246
272
  @prev = @next = @parent = nil
247
273
  self
248
274
  end
@@ -276,11 +302,11 @@ module RootedTree
276
302
 
277
303
  # Children
278
304
  #
279
- # Returns an enumerator that will iterate over each of the node children.
280
- # The default order is left-to-right, but by passing rtl: true the order can
281
- # be reversed.
305
+ # Yields to each of the node children. The default order is left-to-right,
306
+ # but by passing rtl: true the order can be reversed. If a block is not given an enumerator is returned.
282
307
  #
283
- # If a block is given it will be yielded to.
308
+ # Note that the block will catch any StopIteration that is raised and
309
+ # terminate early, returning the value of the exception.
284
310
 
285
311
  def children(rtl: false)
286
312
  return to_enum(__callee__, rtl: rtl) unless block_given?
@@ -300,7 +326,8 @@ module RootedTree
300
326
 
301
327
  # Each
302
328
  #
303
- #
329
+ # Yields first to self and then to each child. If a block is not given an
330
+ # enumerator is returned.
304
331
 
305
332
  def each(&block)
306
333
  return to_enum(__callee__) unless block_given?
@@ -351,7 +378,7 @@ module RootedTree
351
378
 
352
379
  def ==(other)
353
380
  return false unless other.is_a? self.class
354
- return other.leaf? if leaf?
381
+ return false unless degree == other.degree
355
382
 
356
383
  children.to_a == other.children.to_a
357
384
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module RootedTree
2
4
  class Tree
3
5
  attr_reader :root
@@ -7,15 +9,24 @@ module RootedTree
7
9
  @root.freeze
8
10
  end
9
11
 
12
+ def tree
13
+ self
14
+ end
15
+
10
16
  # Degree
11
17
  #
12
18
  # Returns the maximum degree (number of children) in the tree.
13
19
 
14
20
  def degree
15
- max_degree_node = root.each.max_by do |node|
16
- node.degree
17
- end
18
- max_degree_node.degree
21
+ @degree ||= root.max_degree
22
+ end
23
+
24
+ # Depth
25
+ #
26
+ # Returns the maximum depth of the tree.
27
+
28
+ def depth
29
+ @depth ||= root.max_depth
19
30
  end
20
31
  end
21
32
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module RootedTree
4
- VERSION = '0.2.0'
4
+ VERSION = '0.2.1'
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rooted_tree
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.2.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sebastian Lindberg