rooted_tree 0.2.0 → 0.2.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.
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