rubytree 0.6.1 → 0.6.2

Sign up to get free protection for your applications and to get access to all the features.
data/COPYING CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  http://rubytree.rubyforge.org
4
4
 
5
- Copyright (c) 2006-2010 Anupam Sengupta
5
+ Copyright (c) 2006, 2007, 2008, 2009, 2010 Anupam Sengupta (anupamsg at gmail dot com)
6
6
 
7
7
  All rights reserved.
8
8
 
@@ -26,4 +26,4 @@ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSE
26
26
  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27
27
  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
28
 
29
- $Id: COPYING 163 2010-01-03 19:38:25Z anupamsg $
29
+ $Id$
data/ChangeLog CHANGED
@@ -1,3 +1,28 @@
1
+ 2010-01-30 Anupam Sengupta <anupamsg@gmail.com>
2
+
3
+ * lib/tree.rb (Tree): Update the example code to use Ruby
4
+ conventions for the variable names.
5
+ (Tree): updated the documentation.
6
+
7
+ * README: Updated the example to use Ruby conventions for the
8
+ variable names.
9
+
10
+ 2010-01-28 Anupam Sengupta <anupamsg@gmail.com>
11
+
12
+ * Rakefile: Minor documentation change.
13
+
14
+ * README (DOCUMENTATION): Added comments to the example code.
15
+
16
+ * test/test_tree.rb: Documentation clean up.
17
+
18
+ * test/test_binarytree.rb: Documentation clean up.
19
+
20
+ * lib/tree.rb (Tree): Cleaned up documentation. Also some minor
21
+ code refactoring done.
22
+
23
+ * lib/tree/binarytree.rb (Tree): Cleaned up documentation. Minor
24
+ readability improvement in the isLeftChild? and isRightChild? methods.
25
+
1
26
  2010-01-05 Anupam Sengupta <anupamsg@gmail.com>
2
27
 
3
28
  * README: Updated the requirements section.
@@ -207,4 +232,4 @@
207
232
 
208
233
  * Changelog: Added the Changelog file.
209
234
 
210
- $Id: ChangeLog 164 2010-01-04 19:27:12Z anupamsg $
235
+ $Id$
data/History.txt CHANGED
@@ -1,3 +1,7 @@
1
+ === 0.6.2 / 2010-01-30
2
+
3
+ * Updated the documentation.
4
+
1
5
  === 0.6.1 / 2010-01-04
2
6
 
3
7
  * Changed the hard-dependency on the 'structured_warnings' RubyGem to a soft-dependency - which lets Rubytree still
@@ -40,4 +44,4 @@
40
44
 
41
45
  * Minor code refactoring. Changes in the Rakefile.
42
46
 
43
- $Id: History.txt 164 2010-01-04 19:27:12Z anupamsg $
47
+ $Id$
data/README CHANGED
@@ -6,15 +6,16 @@
6
6
  \/ \_/\__,_|_.__/ \__, |\__|_| \___|\___|
7
7
  |___/
8
8
 
9
- (c) 2006, 2007, 2008, 2009, 2010 Anupam Sengupta
9
+ Copyright (c) 2006, 2007, 2008, 2009, 2010 Anupam Sengupta (anupamsg at gmail dot com)
10
10
  http://rubytree.rubyforge.org
11
11
 
12
12
  == DESCRIPTION:
13
13
 
14
- RubyTree is a Ruby implementation of the generic Tree data structure. It provides a generic tree data-structure with
15
- ability to store keyed node-elements in the tree. This implementation is node-centric, where the individual nodes on
16
- the tree are the primary objects and form the leafs of the structure. The implementation mixes in the Enumerable
17
- module.
14
+ RubyTree is a Ruby implementation of the generic tree data structure. It provides a node-based model to store keyed
15
+ node-elements in the tree and simple APIs to access, modify and traverse the structure. RubyTree is node-centric, where
16
+ individual nodes on the tree are the primary compositional and structural elements.
17
+
18
+ This implementation also mixes in the Enumerable module to allow standard access to the tree as a collection.
18
19
 
19
20
  == SYNOPSIS:
20
21
 
@@ -34,24 +35,34 @@ As an example, the following code-snippet implements this tree structure:
34
35
  | GRANDCHILD 1 |
35
36
  +---------------+
36
37
 
37
- # Example
38
- require 'tree'
38
+ # ..... Example starts.
39
+ require 'tree' # Load the library
40
+
41
+ # ..... Create the root node first. Note that every node has a name and an optional content payload.
42
+ root_node = Tree::TreeNode.new("ROOT", "Root Content")
43
+
44
+ # ..... Now insert the child nodes. Note that you can "chain" the child insertions for a given path to any depth.
45
+ root_node << Tree::TreeNode.new("CHILD1", "Child1 Content") << Tree::TreeNode.new("GRANDCHILD1", "GrandChild1 Content")
46
+ root_node << Tree::TreeNode.new("CHILD2", "Child2 Content")
47
+
48
+ # ..... Lets print the representation to stdout. This is primarily used for debugging purposes.
49
+ root_node.printTree
39
50
 
40
- myTreeRoot = Tree::TreeNode.new("ROOT", "Root Content")
41
- myTreeRoot << Tree::TreeNode.new("CHILD1", "Child1 Content") << Tree::TreeNode.new("GRANDCHILD1", "GrandChild1 Content")
42
- myTreeRoot << Tree::TreeNode.new("CHILD2", "Child2 Content")
51
+ # ..... Lets directly access children and grandchildren of the root. The can be "chained" for a given path to any depth.
52
+ child1 = root_node["CHILD1"]
53
+ grand_child1 = root_node["CHILD1"]["GRANDCHILD1"]
43
54
 
44
- myTreeRoot.printTree
55
+ # ..... Now lets retrieve siblings of the current node as an array.
56
+ siblings_of_child1 = child1.siblings
45
57
 
46
- child1 = myTreeRoot["CHILD1"]
47
- grandChild1 = myTreeRoot["CHILD1"]["GRANDCHILD1"]
58
+ # ..... Lets retrieve immediate children of the root node as an array.
59
+ children_of_root = root_node.children
48
60
 
49
- siblingsOfChild1Array = child1.siblings
50
- immediateChildrenArray = myTreeRoot.children
61
+ # ..... This is a depth-first and L-to-R pre-ordered traversal.
62
+ root_node.each { |node| node.content.reverse }
51
63
 
52
- # Process all nodes
53
- myTreeRoot.each { |node| node.content.reverse }
54
- myTreeRoot.remove!(child1) # Remove the child
64
+ # ..... Lets remove a child node from the root node.
65
+ root_node.remove!(child1)
55
66
 
56
67
 
57
68
  == REQUIREMENTS:
@@ -127,7 +138,7 @@ tasks.
127
138
 
128
139
  RubyTree is licensed under the BSD[http://www.opensource.org/licenses/bsd-license.php] license.
129
140
 
130
- Copyright (c) 2006, 2007 Anupam Sengupta
141
+ Copyright (c) 2006, 2007, 2008, 2009, 2010 Anupam Sengupta
131
142
  All rights reserved.
132
143
 
133
144
  Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
@@ -151,4 +162,4 @@ WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWIS
151
162
  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
152
163
 
153
164
 
154
- (Document Revision: $Revision: 164 $ by $Author: anupamsg $)
165
+ (Document Revision: $Revision$ by $Author$)
data/Rakefile CHANGED
@@ -1,10 +1,10 @@
1
1
  # -*- mode: ruby; -*-
2
2
  #
3
- # Rakefile
3
+ # Rakefile - This file is part of the RubyTree package.
4
4
  #
5
- # $Revision: 164 $ by $Author: anupamsg $ on $Date: 2010-01-05 00:57:12 +0530 (Tue, 05 Jan 2010) $
5
+ # $Revision$ by $Author$ on $Date$
6
6
  #
7
- # Copyright (c) 2006, 2007 Anupam Sengupta
7
+ # Copyright (c) 2006, 2007, 2009, 2010 Anupam Sengupta
8
8
  #
9
9
  # All rights reserved.
10
10
  #
@@ -61,6 +61,20 @@ begin
61
61
  self.need_tar = true
62
62
  self.need_zip = true
63
63
 
64
+ # Post installation message
65
+ self.post_install_message = <<MSGEND
66
+ ========================================================================
67
+
68
+ Thank you for installing #{PKG_NAME.capitalize}.
69
+
70
+ Please note that a few APIs have been deprecated since Version 0.6.1
71
+
72
+ Specifically, the 'Tree::TreeNode#depth' method is now deprecated, and
73
+ a new nodeDepth() method has been introduced.
74
+
75
+ ========================================================================
76
+ MSGEND
77
+
64
78
  # Code Metrics ...
65
79
  self.flay_threshold = timebomb 1200, 100 # Default is 1200, 100
66
80
  self.flog_threshold = timebomb 1200, 100 # Default is 1200, 100
data/TODO CHANGED
@@ -1,5 +1,10 @@
1
1
  # -*- mode: org; coding: utf-8-unix; -*-
2
2
 
3
+ * TODO Convert all method names to the canonical /^[_a-z<>=\[|+-\/\*`]+[_a-z0-9_<>=~@\[\]]*[=!\?]?$/ pattern
4
+ See Roodi report at http://getcaliper.com/caliper/tool?tool=roodi&repo=git://github.com/evolve75/RubyTree.git
5
+ * TODO Fix the TreeNode#root method to return nil for root's root.
6
+ * TODO Fix the marshal_load method. This probably needs to be a class method.
7
+ * TODO Fix the semantic inconsistency between the TreeNode#first|lastSibling method and the siblings method w.r.t. the root
3
8
  * TODO Create the basic UML diagrams and upload to the Site
4
9
  DEADLINE: <2010-01-04 Mon>
5
10
 
@@ -16,4 +21,4 @@
16
21
 
17
22
 
18
23
 
19
- $Id: TODO 154 2010-01-03 18:01:28Z anupamsg $
24
+ $Id$
data/lib/tree.rb CHANGED
@@ -1,11 +1,11 @@
1
- # tree.rb
1
+ # tree.rb - This file is part of the RubyTree package.
2
2
  #
3
- # $Revision: 164 $ by $Author: anupamsg $ on $Date: 2010-01-05 00:57:12 +0530 (Tue, 05 Jan 2010) $
3
+ # $Revision$ by $Author$ on $Date$
4
4
  #
5
- # = tree.rb - Generic Multi-way Tree implementation
5
+ # = tree.rb - Generic implementation of an N-ary tree data structure.
6
6
  #
7
7
  # Provides a generic tree data structure with ability to
8
- # store keyed node elements in the tree. The implementation
8
+ # store keyed node elements in the tree. This implementation
9
9
  # mixes in the Enumerable module.
10
10
  #
11
11
  # Author:: Anupam Sengupta (anupamsg@gmail.com)
@@ -41,29 +41,42 @@
41
41
  # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
42
42
  #
43
43
 
44
- # This module provides a TreeNode class which is the primary class for all
45
- # nodes represented in the Tree.
46
- # This module mixes in the Enumerable module.
44
+ # This module provides a TreeNode class which is the primary class for representing
45
+ # nodes in the tree.
46
+ #
47
+ # This module mixes in the Enumerable module, and also acts as the namespace for all
48
+ # classes in RubyTree.
47
49
  module Tree
48
50
 
49
51
  # Rubytree Package Version
50
- VERSION = '0.6.1'
52
+ VERSION = '0.6.2'
51
53
 
52
54
  # == TreeNode Class Description
53
55
  #
54
- # The node class for the tree representation. the nodes are +named+ and have a
55
- # place-holder for the node data (i.e., the `content' of the node). The node
56
- # names are required to be unique. In addition, the node provides navigation
57
- # methods to traverse the tree.
56
+ # This class models the nodes for an N-ary tree data structue. The nodes are +named+
57
+ # and have a place-holder for the node data (i.e., `content' of the node). The node
58
+ # names are required to be *unique* within the tree.
59
+ #
60
+ # The node content is not required to be unique across different nodes in the tree, and
61
+ # can be +nil+ as well.
62
+ #
63
+ # The class provides various traversal methods to navigate the tree,
64
+ # methods to modify contents of the node or to change position of the node in the tree
65
+ # and methods to change structure of the tree.
58
66
  #
59
- # A node can have any number of child nodes attached to it. Note that while
60
- # this implementation does not support directed graphs, the class itself makes
61
- # no restrictions on associating a node's CONTENT with multiple parent nodes.
67
+ # A node can have any number of child nodes attached to it and hence can be used to create N-ary trees.
68
+ # Access to the child nodes can be made in order (with the conventional left to right access), or
69
+ # randomly.
70
+ #
71
+ # The node also provides direct access to its parent and other superior parents in the path to
72
+ # root of the tree. In addition, a node can also access its sibling nodes, if present.
73
+ # Note that while this implementation does not explicitly support directed graphs, the class itself makes
74
+ # no restrictions on associating a node's +CONTENT+ with multiple nodes in the tree.
62
75
  #
63
76
  #
64
77
  # == Example
65
78
  #
66
- # The following code-snippet implements this tree structure:
79
+ # The following example implements this tree structure:
67
80
  #
68
81
  # +------------+
69
82
  # | ROOT |
@@ -81,36 +94,38 @@ module Tree
81
94
  #
82
95
  # require 'tree'
83
96
  #
84
- # myTreeRoot = Tree::TreeNode.new("ROOT", "Root Content")
97
+ # root_node = Tree::TreeNode.new("ROOT", "Root Content")
85
98
  #
86
- # myTreeRoot << Tree::TreeNode.new("CHILD1", "Child1 Content") << Tree::TreeNode.new("GRANDCHILD1", "GrandChild1 Content")
99
+ # root_node << Tree::TreeNode.new("CHILD1", "Child1 Content") << Tree::TreeNode.new("GRANDCHILD1", "GrandChild1 Content")
87
100
  #
88
- # myTreeRoot << Tree::TreeNode.new("CHILD2", "Child2 Content")
101
+ # root_node << Tree::TreeNode.new("CHILD2", "Child2 Content")
89
102
  #
90
- # myTreeRoot.printTree
103
+ # root_node.printTree
91
104
  #
92
- # child1 = myTreeRoot["CHILD1"]
105
+ # child1 = root_node["CHILD1"]
93
106
  #
94
- # grandChild1 = myTreeRoot["CHILD1"]["GRANDCHILD1"]
107
+ # grand_child1 = root_node["CHILD1"]["GRANDCHILD1"]
95
108
  #
96
- # siblingsOfChild1Array = child1.siblings
109
+ # siblings_of_child1 = child1.siblings
97
110
  #
98
- # immediateChildrenArray = myTreeRoot.children
111
+ # children_of_root = root_node.children
99
112
  #
100
113
  # # Process all nodes
101
114
  #
102
- # myTreeRoot.each { |node| node.content.reverse }
115
+ # root_node.each { |node| node.content.reverse }
103
116
  #
104
- # myTreeRoot.remove!(child1) # Remove the child
117
+ # root_node.remove!(child1) # Remove the child
105
118
  #
106
119
  class TreeNode
107
120
  include Enumerable
108
121
 
109
- # Name of this Node
122
+ # Name of this node. Expected to be unique within the tree.
110
123
  attr_reader :name
111
- # Content of this Node
124
+
125
+ # Content of this node. Can be +nil+.
112
126
  attr_accessor :content
113
- # Parent of this Node
127
+
128
+ # Parent of this node. Will be +nil+ for root nodes.
114
129
  attr_reader :parent
115
130
 
116
131
 
@@ -128,8 +143,8 @@ module Tree
128
143
  @children = []
129
144
  end
130
145
 
131
- # Returns a copy of this node, with the parent and children links removed. The original node remains attached to
132
- # its tree.
146
+ # Returns a copy of the receiver node, with its parent and children links removed.
147
+ # The original node remains attached to its tree.
133
148
  def detached_copy
134
149
  Tree::TreeNode.new(@name, @content ? @content.clone : nil)
135
150
  end
@@ -143,8 +158,10 @@ module Tree
143
158
  " Total Nodes: #{size()}"
144
159
  end
145
160
 
146
- # Returns an array of ancestors in reversed order (the first element is the
147
- # immediate parent). Returns +nil+ if this is the root node.
161
+ # Returns an array of ancestors of the receiver node in reversed order
162
+ # (the first element is the immediate parent of the receiver).
163
+ #
164
+ # Returns +nil+ if the receiver is a root node.
148
165
  def parentage
149
166
  return nil if isRoot?
150
167
 
@@ -158,23 +175,38 @@ module Tree
158
175
  parentageArray
159
176
  end
160
177
 
161
- # Protected method to set the parent node.
162
- # This method should NOT be invoked by client code.
163
- def parent=(parent)
178
+ # Protected method to set the parent node for the receiver node.
179
+ # This method should *NOT* be invoked by client code.
180
+ #
181
+ # Returns the parent.
182
+ def parent=(parent) # :nodoc:
164
183
  @parent = parent
165
184
  end
166
185
 
167
- # Convenience synonym for TreeNode#add method. This method allows a convenient
168
- # method to add children hierarchies in the tree.
186
+ # Convenience synonym for TreeNode#add method.
187
+ #
188
+ # This method allows an easy method to add node hierarchies to the tree
189
+ # on a given path via chaining the method calls to successive child nodes.
169
190
  #
170
- # E.g. root << child << grand_child
191
+ # Example: <tt>root << child << grand_child</tt>
192
+ #
193
+ # Returns the added child node.
171
194
  def <<(child)
172
195
  add(child)
173
196
  end
174
197
 
175
- # Adds the specified child node to the receiver node. The child node's
176
- # parent is set to be the receiver. The child is added as the last child in
177
- # the current list of children for the receiver node.
198
+ # Adds the specified child node to the receiver node.
199
+ #
200
+ # This method can also be used for *grafting* a subtree into the receiver node's tree, if the specified child node
201
+ # is the root of a subtree (i.e., has child nodes under it).
202
+ #
203
+ # The receiver node becomes parent of the node passed in as the argument, and
204
+ # the child is added as the last child ("right most") in the current set of
205
+ # children of the receiver node.
206
+ #
207
+ # Returns the added child node.
208
+ #
209
+ # An exception is raised if another child node with the same name exists.
178
210
  def add(child)
179
211
  raise "Child already added" if @childrenHash.has_key?(child.name)
180
212
 
@@ -182,12 +214,15 @@ module Tree
182
214
  @children << child
183
215
  child.parent = self
184
216
  return child
185
-
186
217
  end
187
218
 
188
- # Removes the specified child node from the receiver node. The removed
189
- # children nodes are orphaned but available if an alternate reference
190
- # exists.
219
+ # Removes the specified child node from the receiver node.
220
+ #
221
+ # This method can also be used for *pruning* a subtree, in cases where the removed child node is
222
+ # the root of the subtree to be pruned.
223
+ #
224
+ # The removed child node is orphaned but accessible if an alternate reference exists. If accesible via
225
+ # an alternate reference, the removed child will report itself as a root node for its subtree.
191
226
  #
192
227
  # Returns the child node.
193
228
  def remove!(child)
@@ -197,13 +232,18 @@ module Tree
197
232
  return child
198
233
  end
199
234
 
200
- # Removes this node from its parent. If this is the root node, then does
201
- # nothing.
235
+ # Removes the receiver node from its parent. The reciever node becomes the new root for its subtree.
236
+ #
237
+ # If this is the root node, then does nothing.
238
+ #
239
+ # Returns self (the removed receiver node) if the operation is successful, and +nil+ otherwise.
202
240
  def removeFromParent!
203
241
  @parent.remove!(self) unless isRoot?
204
242
  end
205
243
 
206
244
  # Removes all children from the receiver node.
245
+ #
246
+ # Returns the receiver node.
207
247
  def removeAll!
208
248
  for child in @children
209
249
  child.setAsRoot!
@@ -213,35 +253,38 @@ module Tree
213
253
  self
214
254
  end
215
255
 
216
- # Returns +true+ if this node has any associated content.
256
+ # Returns +true+ if the receiver node has any associated content.
217
257
  def hasContent?
218
258
  @content != nil
219
259
  end
220
260
 
221
- # Protected method which sets this node as a root node.
222
- def setAsRoot!
261
+ # Protected method which sets the receiver node as a root node.
262
+ #
263
+ # Returns +nil+.
264
+ def setAsRoot! # :nodoc:
223
265
  @parent = nil
224
266
  end
225
267
 
226
- # Returns +true+ if this is a root node. Note that
268
+ # Returns +true+ if the receiver is a root node. Note that
227
269
  # orphaned children will also be reported as root nodes.
228
270
  def isRoot?
229
271
  @parent == nil
230
272
  end
231
273
 
232
- # Returns +true+ if this node has any immediate child nodes.
274
+ # Returns +true+ if the receiver node has any immediate child nodes.
233
275
  def hasChildren?
234
276
  @children.length != 0
235
277
  end
236
278
 
237
- # Returns +true+ if this node is a 'leaf' - i.e., one without
279
+ # Returns +true+ if the receiver node is a 'leaf' - i.e., one without
238
280
  # any children.
239
281
  def isLeaf?
240
282
  !hasChildren?
241
283
  end
242
284
 
243
- # Returns an array of all the immediate children. If a block is given,
244
- # yields each child node to the block.
285
+ # Returns an array of all the immediate children of the receiver node.
286
+ #
287
+ # If a block is given, yields each child node to the block traversing from left to right.
245
288
  def children
246
289
  if block_given?
247
290
  @children.each {|child| yield child}
@@ -250,34 +293,37 @@ module Tree
250
293
  end
251
294
  end
252
295
 
253
- # Returns the first child of this node. Will return nil if no children are
254
- # present.
296
+ # Returns the first child of the receiver node.
297
+ #
298
+ # Will return +nil+ if no children are present.
255
299
  def firstChild
256
300
  children.first
257
301
  end
258
302
 
259
- # Returns the last child of this node. Will return nil if no children are
260
- # present.
303
+ # Returns the last child of the receiver node.
304
+ #
305
+ # Will return +nil+ if no children are present.
261
306
  def lastChild
262
307
  children.last
263
308
  end
264
309
 
265
- # Returns every node (including the receiver node) from the tree to the
266
- # specified block. The traversal is depth first and from left to right in
267
- # pre-ordered sequence.
268
- def each &block
310
+ # Traverses every node (including the receiver node) from the (sub)tree
311
+ # by yielding the node to the specified block.
312
+ #
313
+ # The traversal is depth-first and from left to right in pre-ordered sequence.
314
+ def each &block # :yields: node
269
315
  yield self
270
316
  children { |child| child.each(&block) }
271
317
  end
272
318
 
273
- # Traverses the tree in a pre-ordered sequence. This is equivalent to
319
+ # Traverses the tree in a pre-ordered sequence. This is equivalent to
274
320
  # TreeNode#each
275
- def preordered_each &block
321
+ def preordered_each &block # :yields: node
276
322
  each(&block)
277
323
  end
278
324
 
279
- # Performs breadth first traversal of the tree starting at this node. The
280
- # traversal in a given level is from left to right.
325
+ # Performs breadth first traversal of the tree starting at the receiver node. The
326
+ # traversal at a given level is from left to right.
281
327
  def breadth_each &block
282
328
  node_queue = [self] # Create a queue with self as the initial entry
283
329
 
@@ -290,18 +336,21 @@ module Tree
290
336
  end
291
337
  end
292
338
 
293
- # Yields all leaf nodes from this node to the specified block. May yield
294
- # this node as well if this is a leaf node. Leaf traversal depth first and
295
- # left to right.
339
+ # Yields all leaf nodes from the receiver node to the specified block.
340
+ #
341
+ # May yield this node as well if this is a leaf node.
342
+ # Leaf traversal is depth-first and left to right.
296
343
  def each_leaf &block
297
344
  self.each { |node| yield(node) if node.isLeaf? }
298
345
  end
299
346
 
300
347
  # Returns the requested node from the set of immediate children.
301
348
  #
302
- # If the parameter is _numeric_, then the in-sequence array of children is
303
- # accessed (see Tree#children). If the parameter is not _numeric_, then it
304
- # is assumed to be the *name* of the child node to be returned.
349
+ # If the argument is _numeric_, then the in-sequence array of children is
350
+ # accessed (see Tree#children). If the argument is *NOT* _numeric_, then it
351
+ # is assumed to be *name* of the child node to be returned.
352
+ #
353
+ # Raises an exception is the requested child node is not found.
305
354
  def [](name_or_index)
306
355
  raise "Name_or_index needs to be provided" if name_or_index == nil
307
356
 
@@ -312,11 +361,11 @@ module Tree
312
361
  end
313
362
  end
314
363
 
315
- # Returns the total number of nodes in this tree, including this node.
364
+ # Returns the total number of nodes in this (sub)tree, including the receiver node.
316
365
  #
317
366
  # Size of the tree is defined as:
318
367
  #
319
- # Size:: The total number nodes in the subtree including this node.
368
+ # Size:: Total number nodes in the subtree including the receiver node.
320
369
  def size
321
370
  @children.inject(1) {|sum, node| sum + node.size}
322
371
  end
@@ -344,105 +393,131 @@ module Tree
344
393
  children { |child| child.printTree(level + 1)}
345
394
  end
346
395
 
347
- # Returns the root for this tree. Root's root is itself (Hence beware of any loop that can become infinite!)
396
+ # Returns root node for the (sub)tree to which the receiver node belongs.
397
+ #
398
+ # Note that a root node's root is itself (*beware* of any loop construct that may become infinite!)
399
+ #--
400
+ # TODO: We should perhaps return nil as root's root.
401
+ #++
348
402
  def root
349
403
  root = self
350
404
  root = root.parent while !root.isRoot?
351
405
  root
352
406
  end
353
407
 
354
- # Returns the first sibling for this node. If this is the root node, returns
408
+ # Returns the first sibling for the receiver node. If this is the root node, returns
355
409
  # itself.
410
+ #
411
+ # 'First' sibling is defined as follows:
412
+ # First sibling:: The left-most child of the receiver's parent, which may be the receiver itself
413
+ #--
414
+ # TODO: Fix the inconsistency of returning root as its first sibling, and returning a
415
+ # a nil array for siblings for the node.
416
+ #++
356
417
  def firstSibling
357
- if isRoot?
358
- self
359
- else
360
- parent.children.first
361
- end
418
+ isRoot? ? self : parent.children.first
362
419
  end
363
420
 
364
- # Returns true if this node is the first sibling.
421
+ # Returns true if the receiver node is the first sibling.
365
422
  def isFirstSibling?
366
423
  firstSibling == self
367
424
  end
368
425
 
369
- # Returns the last sibling for this node. If this node is the root, returns
426
+ # Returns the last sibling for the receiver node. If this is the root node, returns
370
427
  # itself.
428
+ #
429
+ # 'Last' sibling is defined as follows:
430
+ # Last sibling:: The right-most child of the receiver's parent, which may be the receiver itself
431
+ #--
432
+ # TODO: Fix the inconsistency of returning root as its last sibling, and returning a
433
+ # a nil array for siblings for the node.
434
+ #++
371
435
  def lastSibling
372
- if isRoot?
373
- self
374
- else
375
- parent.children.last
376
- end
436
+ isRoot? ? self : parent.children.last
377
437
  end
378
438
 
379
- # Returns true if his node is the last sibling
439
+ # Returns true if the receivere node is the last sibling.
380
440
  def isLastSibling?
381
441
  lastSibling == self
382
442
  end
383
443
 
384
- # Returns an array of siblings for this node.
385
- # If a block is provided, yields each of the sibling
386
- # nodes to the block. The root always has nil siblings.
444
+ # Returns an array of siblings for the receiver node. The receiver node is excluded.
445
+ #
446
+ # If a block is provided, yields each of the sibling nodes to the block.
447
+ # The root always has +nil+ siblings.
448
+ #--
449
+ # TODO: Fix the inconsistency of returning root as its first/last sibling, and returning a
450
+ # a nil array for siblings for the node.
451
+ #++
387
452
  def siblings
388
453
  return nil if isRoot?
454
+
389
455
  if block_given?
390
456
  for sibling in parent.children
391
457
  yield sibling if sibling != self
392
458
  end
393
459
  else
394
460
  siblings = []
395
- parent.children {|sibling| siblings << sibling if sibling != self}
461
+ parent.children {|my_sibling| siblings << my_sibling if my_sibling != self}
396
462
  siblings
397
463
  end
398
464
  end
399
465
 
400
- # Returns true if this node is the only child of its parent
466
+ # Returns true if the receiver node is the only child of its parent.
401
467
  def isOnlyChild?
402
468
  parent.children.size == 1
403
469
  end
404
470
 
405
- # Returns the next sibling for this node. Will return nil if no subsequent
406
- # node is present.
471
+ # Returns the next sibling for the receiver node.
472
+ # The 'next' node is defined as the node to right of the receiver node.
473
+ #
474
+ # Will return +nil+ if no subsequent node is present.
407
475
  def nextSibling
408
476
  if myidx = parent.children.index(self)
409
477
  parent.children.at(myidx + 1)
410
478
  end
411
479
  end
412
480
 
413
- # Returns the previous sibling for this node. Will return nil if no
414
- # subsequent node is present.
481
+ # Returns the previous sibling for the receiver node.
482
+ # The 'previous' node is defined as the node to left of the receiver node.
483
+ #
484
+ # Will return nil if no predecessor node is present.
415
485
  def previousSibling
416
486
  if myidx = parent.children.index(self)
417
487
  parent.children.at(myidx - 1) if myidx > 0
418
488
  end
419
489
  end
420
490
 
421
- # Provides a comparision operation for the nodes. Comparision
422
- # is based on the natural character-set ordering for the
423
- # node names.
491
+ # Provides a comparision operation for the nodes.
492
+ #
493
+ # Comparision is based on the natural character-set ordering of the *node name*.
424
494
  def <=>(other)
425
495
  return +1 if other == nil
426
496
  self.name <=> other.name
427
497
  end
428
498
 
429
- # Freezes all nodes in the tree
499
+ # Freezes all nodes in the (sub)tree rooted at the receiver node.
430
500
  def freezeTree!
431
501
  each {|node| node.freeze}
432
502
  end
433
503
 
434
- # Creates the marshal-dump represention of the tree rooted at this node.
504
+ # Returns a marshal-dump represention of the (sub)tree rooted at the receiver node.
435
505
  def marshal_dump
436
506
  self.collect { |node| node.createDumpRep }
437
507
  end
438
508
 
439
- # Creates a dump representation and returns the same as a hash.
440
- def createDumpRep
509
+ # Creates a dump representation of the reciever node and returns the same as a hash.
510
+ def createDumpRep # :nodoc:
441
511
  { :name => @name, :parent => (isRoot? ? nil : @parent.name), :content => Marshal.dump(@content)}
442
512
  end
443
513
 
444
- # Loads a marshalled dump of the tree and returns the root node of the
514
+ # Loads a marshalled dump of a tree and returns the root node of the
445
515
  # reconstructed tree. See the Marshal class for additional details.
516
+ #
517
+ #--
518
+ # TODO: This method probably should be a class method. It currently clobbers self
519
+ # and makes itself the root.
520
+ #++
446
521
  def marshal_load(dumped_tree_array)
447
522
  nodes = { }
448
523
  for node_hash in dumped_tree_array do
@@ -458,37 +533,41 @@ module Tree
458
533
  initialize(name, content)
459
534
 
460
535
  nodes[name] = self # Add self to the list of nodes
461
- end
536
+ end
462
537
  end
463
538
  end
464
539
 
465
- # Returns height of the (sub)tree from this node. Height of a node is defined as:
540
+ # Returns height of the (sub)tree from the receiver node. Height of a node is defined as:
541
+ #
542
+ # Height:: Length of the longest downward path to a leaf from the node.
466
543
  #
467
- # Height:: Length of the longest downward path to a leaf from the node. Height of from the root node is height of
468
- # the tree. The height of a leaf node is zero.
544
+ # - Height from a root node is height of the entire tree.
545
+ # - The height of a leaf node is zero.
469
546
  def nodeHeight
470
547
  return 0 if isLeaf?
471
548
  1 + @children.collect { |child| child.nodeHeight }.max
472
549
  end
473
550
 
474
- # Returns depth this node in its (sub)tree. Depth of a node is defined as:
551
+ # Returns depth of the receiver node in its tree. Depth of a node is defined as:
475
552
  #
476
553
  # Depth:: Length of the node's path to its root. Depth of a root node is zero.
477
554
  #
478
- # Note that the deprecated method Tree::TreeNode#depth was incorrectly computing this value. Please replace all
479
- # calls to the old method by this one.
555
+ # *Note* that the deprecated method Tree::TreeNode#depth was incorrectly computing this value.
556
+ # Please replace all calls to the old method with Tree::TreeNode#nodeDepth instead.
480
557
  def nodeDepth
481
558
  return 0 if isRoot?
482
559
  1 + parent.nodeDepth
483
560
  end
484
561
 
485
- # Returns depth of the tree from this node. A single leaf node has a depth of 1.
562
+ # Returns depth of the tree from the receiver node. A single leaf node has a depth of 1.
563
+ #
564
+ # This method is *DEPRECATED* and may be removed in the subsequent releases.
565
+ # Note that the value returned by this method is actually the:
486
566
  #
487
- # This method is *DEPRECATED* and may be removed in the subsequent releases. Note that per convention, the value
488
- # returned by this method is actually the _height_ + 1 of the node, *not* the _depth_.
567
+ # _height_ + 1 of the node, *NOT* the _depth_.
489
568
  #
490
- # For correct and conventional behavior, please use Tree::TreeNode#nodeDepth and Tree::TreeNode#nodeHeight methods
491
- # instead.
569
+ # For correct and conventional behavior, please use Tree::TreeNode#nodeDepth and
570
+ # Tree::TreeNode#nodeHeight methods instead.
492
571
  def depth
493
572
  begin
494
573
  require 'structured_warnings' # To enable a nice way of deprecating of the depth method.
@@ -498,17 +577,17 @@ module Tree
498
577
  warn 'Tree::TreeNode#depth() method is deprecated. Please use nodeDepth() or nodeHeight() instead (bug # 22535)'
499
578
  end
500
579
 
501
-
502
580
  return 1 if isLeaf?
503
581
  1 + @children.collect { |child| child.depth }.max
504
582
  end
505
583
 
506
- # Returns breadth of the tree at this node level. A single node has a breadth of 1. Breadth is defined to be the
507
- # number of nodes present as siblings to this node + 1 (this node itself), i.e., the number of children the parent
508
- # of this node has.
584
+ # Returns breadth of the tree at the receiver node's level.
585
+ # A single node without siblings has a breadth of 1.
586
+ #
587
+ # Breadth is defined to be:
588
+ # Breadth:: Number of sibling nodes to this node + 1 (this node itself), i.e., the number of children the parent of this node has.
509
589
  def breadth
510
- return 1 if isRoot?
511
- parent.children.size
590
+ isRoot? ? 1 : parent.children.size
512
591
  end
513
592
 
514
593
  protected :parent=, :setAsRoot!, :createDumpRep
@@ -1,12 +1,11 @@
1
- # binarytree.rb
1
+ # binarytree.rb - This file is part of the RubyTree package.
2
2
  #
3
- # $Revision: 160 $ by $Author: anupamsg $ on $Date: 2010-01-03 23:58:07 +0530 (Sun, 03 Jan 2010) $
3
+ # $Revision$ by $Author$ on $Date$
4
4
  #
5
- # = binarytree.rb - Binary Tree implementation
5
+ # = binarytree.rb - An implementation of the binary tree data structure.
6
6
  #
7
- # Provides a generic tree data structure with ability to
8
- # store keyed node elements in the tree. The implementation
9
- # mixes in the Enumerable module.
7
+ # Provides a binary tree data structure with ability to
8
+ # store two node elements as children at each node in the tree.
10
9
  #
11
10
  # Author:: Anupam Sengupta (anupamsg@gmail.com)
12
11
  #
@@ -45,61 +44,67 @@ require 'tree'
45
44
 
46
45
  module Tree
47
46
 
48
- # Provides a Binary tree implementation. This tree node allows only two child nodes (left and right childs). It also
47
+ # Provides a Binary tree implementation. This node allows only two child nodes (left and right child). It also
49
48
  # provides direct access to the left or right child, including assignment to the same.
49
+ #
50
+ # This inherits from the Tree::TreeNode class.
50
51
  class BinaryTreeNode < TreeNode
51
52
 
52
- # Adds the specified child node to the receiver node. The child node's parent is set to be the receiver. The child
53
- # nodes are added in the order of addition, i.e., the first child added becomes the left node, and the second child
54
- # will be the second node.
53
+ # Adds the specified child node to the receiver node. The child node's parent is set to be the receiver.
54
+ #
55
+ # The child nodes are added in the order of addition, i.e., the first child added becomes the left node, and the
56
+ # second child added will be the second node.
55
57
  #
56
58
  # If only one child is present, then this will be the left child.
59
+ #
60
+ # An exception is raised if two children are already present.
57
61
  def add(child)
58
62
  raise "Already has two child nodes" if @children.size == 2
59
63
 
60
64
  super(child)
61
65
  end
62
66
 
63
- # Returns the left child node. Note that left Child == first Child.
67
+ # Returns the left child of the receiver node. Note that left Child == first Child.
64
68
  def leftChild
65
69
  children.first
66
70
  end
67
71
 
68
- # Returns the right child node. Note that right child == last child unless there is only one child. Returns +nil+
69
- # if the right child does not exist.
72
+ # Returns the right child of the receiver node. Note that right child == last child unless there is only one child.
73
+ #
74
+ # Returns +nil+ if the right child does not exist.
70
75
  def rightChild
71
76
  children[1]
72
77
  end
73
78
 
74
- # Sets the left child. If a previous child existed, it is replaced.
79
+ # Sets the left child of the receiver node. If a previous child existed, it is replaced.
75
80
  def leftChild=(child)
76
81
  @children[0] = child
77
82
  @childrenHash[child.name] = child if child # Assign the name mapping
78
83
  end
79
84
 
80
- # Sets the right child. If a previous child existed, it is replaced.
85
+ # Sets the right child of the receiver node. If a previous child existed, it is replaced.
81
86
  def rightChild=(child)
82
87
  @children[1] = child
83
88
  @childrenHash[child.name] = child if child # Assign the name mapping
84
89
  end
85
90
 
86
- # Returns +true+ if this is the left child of its parent. Always returns +false+ if this is the root node.
91
+ # Returns +true+ if the receiver node is the left child of its parent. Always returns +false+ if it is a root node.
87
92
  def isLeftChild?
88
- return nil if isRoot?
93
+ return false if isRoot?
89
94
  self == parent.leftChild
90
95
  end
91
96
 
92
- # Returns +true+ if this is the right child of its parent. Always returns +false+ if this is the root node.
97
+ # Returns +true+ if the receiver node is the right child of its parent. Always returns +false+ if it is a root node.
93
98
  def isRightChild?
94
- return nil if isRoot?
99
+ return false if isRoot?
95
100
  self == parent.rightChild
96
101
  end
97
102
 
98
- # Swaps the left and right child nodes with each other.
103
+ # Swaps the left and right child nodes of the receiver node with each other.
99
104
  def swap_children
100
- tempChild = leftChild
101
- self.leftChild= rightChild
102
- self.rightChild= tempChild
105
+ tempChild = leftChild
106
+ self.leftChild = rightChild
107
+ self.rightChild = tempChild
103
108
  end
104
109
  end
105
110
 
@@ -1,8 +1,8 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
- # test_binarytree.rb
3
+ # test_binarytree.rb - This file is part of the RubyTree package.
4
4
  #
5
- # $Revision: 146 $ by $Author: anupamsg $ on $Date: 2010-01-02 14:53:30 +0530 (Sat, 02 Jan 2010) $
5
+ # $Revision$ by $Author$ on $Date$
6
6
  #
7
7
  # Copyright (c) 2006, 2007, 2008, 2009, 2010 Anupam Sengupta
8
8
  #
@@ -38,7 +38,7 @@ require 'test/unit'
38
38
  require 'tree/binarytree'
39
39
 
40
40
  module TestTree
41
- # Test class for the Tree node.
41
+ # Test class for the binary tree node.
42
42
  class TestBinaryTreeNode < Test::Unit::TestCase
43
43
 
44
44
  def setup
data/test/test_tree.rb CHANGED
@@ -1,8 +1,8 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
- # testtree.rb
3
+ # testtree.rb - This file is part of the RubyTree package.
4
4
  #
5
- # $Revision: 164 $ by $Author: anupamsg $ on $Date: 2010-01-05 00:57:12 +0530 (Tue, 05 Jan 2010) $
5
+ # $Revision$ by $Author$ on $Date$
6
6
  #
7
7
  # Copyright (c) 2006, 2007, 2008, 2009, 2010 Anupam Sengupta
8
8
  #
@@ -41,7 +41,7 @@ module TestTree
41
41
  # Test class for the Tree node.
42
42
  class TestTreeNode < Test::Unit::TestCase
43
43
 
44
- Person = Struct::new(:First, :last)
44
+ Person = Struct::new(:First, :last) # A simple structure to use as the content for the nodes.
45
45
 
46
46
  def setup
47
47
  @root = Tree::TreeNode.new("ROOT", "Root Node")
@@ -83,16 +83,16 @@ module TestTree
83
83
 
84
84
  # This test is for the root alone - without any children being linked
85
85
  def test_root_setup
86
- assert_not_nil(@root, "Root cannot be nil")
87
- assert_nil(@root.parent, "Parent of root node should be nil")
88
- assert_not_nil(@root.name, "Name should not be nil")
89
- assert_equal("ROOT", @root.name, "Name should be 'ROOT'")
90
- assert_equal("Root Node", @root.content, "Content should be 'Root Node'")
91
- assert(@root.isRoot?, "Should identify as root")
92
- assert(!@root.hasChildren?, "Cannot have any children")
93
- assert(@root.hasContent?, "This root should have content")
94
- assert_equal(1, @root.size, "Number of nodes should be one")
95
- assert_nil(@root.siblings, "This root does not have any children")
86
+ assert_not_nil(@root , "Root cannot be nil")
87
+ assert_nil(@root.parent , "Parent of root node should be nil")
88
+ assert_not_nil(@root.name , "Name should not be nil")
89
+ assert_equal("ROOT" , @root.name, "Name should be 'ROOT'")
90
+ assert_equal("Root Node" , @root.content, "Content should be 'Root Node'")
91
+ assert(@root.isRoot? , "Should identify as root")
92
+ assert(!@root.hasChildren? , "Cannot have any children")
93
+ assert(@root.hasContent? , "This root should have content")
94
+ assert_equal(1 , @root.size, "Number of nodes should be one")
95
+ assert_nil(@root.siblings , "This root does not have any children")
96
96
 
97
97
  assert_equal(0, @root.nodeHeight, "Root's height before adding any children is 0")
98
98
  assert_raise(RuntimeError) { Tree::TreeNode.new(nil) }
@@ -102,16 +102,16 @@ module TestTree
102
102
  def test_root
103
103
  loadChildren
104
104
 
105
- assert_same(@root, @root.root, "Root's root is self")
106
- assert_same(@root, @child1.root, "Root should be ROOT")
107
- assert_same(@root, @child4.root, "Root should be ROOT")
108
- assert_equal(2, @root.nodeHeight, "Root's height after adding the children should be 2")
105
+ assert_same(@root , @root.root, "Root's root is self")
106
+ assert_same(@root , @child1.root, "Root should be ROOT")
107
+ assert_same(@root , @child4.root, "Root should be ROOT")
108
+ assert_equal(2 , @root.nodeHeight, "Root's height after adding the children should be 2")
109
109
  end
110
110
 
111
111
  def test_hasContent_eh
112
112
  aNode = Tree::TreeNode.new("A Node")
113
- assert_nil(aNode.content, "The node should not have content")
114
- assert(!aNode.hasContent?, "The node should not have content")
113
+ assert_nil(aNode.content , "The node should not have content")
114
+ assert(!aNode.hasContent? , "The node should not have content")
115
115
 
116
116
  aNode.content = "Something"
117
117
  assert_not_nil(aNode.content, "The node should now have content")
@@ -496,8 +496,11 @@ module TestTree
496
496
  @root.content = "ABC"
497
497
  assert_equal("ABC", @root.content, "Content should be 'ABC'")
498
498
  @root.freezeTree!
499
- assert_raise(TypeError) {@root.content = "123"}
500
- assert_raise(TypeError) {@root[0].content = "123"}
499
+ # Note: The error raised here depends on the Ruby version.
500
+ # For Ruby > 1.9, RuntimeError is raised
501
+ # For Ruby ~ 1.8, TypeError is raised
502
+ assert_raise(RuntimeError, TypeError) {@root.content = "123"}
503
+ assert_raise(RuntimeError, TypeError) {@root[0].content = "123"}
501
504
  end
502
505
 
503
506
  # Test whether the content is accesible
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rubytree
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.1
4
+ version: 0.6.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Anupam Sengupta
@@ -9,9 +9,29 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2010-01-05 00:00:00 +05:30
12
+ date: 2010-01-30 00:00:00 +05:30
13
13
  default_executable:
14
14
  dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: rubyforge
17
+ type: :development
18
+ version_requirement:
19
+ version_requirements: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: 2.0.3
24
+ version:
25
+ - !ruby/object:Gem::Dependency
26
+ name: gemcutter
27
+ type: :development
28
+ version_requirement:
29
+ version_requirements: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: 0.3.0
34
+ version:
15
35
  - !ruby/object:Gem::Dependency
16
36
  name: hoe
17
37
  type: :development
@@ -20,13 +40,14 @@ dependencies:
20
40
  requirements:
21
41
  - - ">="
22
42
  - !ruby/object:Gem::Version
23
- version: 2.4.0
43
+ version: 2.5.0
24
44
  version:
25
45
  description: |-
26
- RubyTree is a Ruby implementation of the generic Tree data structure. It provides a generic tree data-structure with
27
- ability to store keyed node-elements in the tree. This implementation is node-centric, where the individual nodes on
28
- the tree are the primary objects and form the leafs of the structure. The implementation mixes in the Enumerable
29
- module.
46
+ RubyTree is a Ruby implementation of the generic tree data structure. It provides a node-based model to store keyed
47
+ node-elements in the tree and simple APIs to access, modify and traverse the structure. RubyTree is node-centric, where
48
+ individual nodes on the tree are the primary compositional and structural elements.
49
+
50
+ This implementation also mixes in the Enumerable module to allow standard access to the tree as a collection.
30
51
  email:
31
52
  - anupamsg@gmail.com
32
53
  executables: []
@@ -56,7 +77,18 @@ has_rdoc: true
56
77
  homepage: http://rubytree.rubyforge.org
57
78
  licenses: []
58
79
 
59
- post_install_message:
80
+ post_install_message: |
81
+ ========================================================================
82
+
83
+ Thank you for installing Rubytree.
84
+
85
+ Please note that a few APIs have been deprecated since Version 0.6.1
86
+
87
+ Specifically, the 'Tree::TreeNode#depth' method is now deprecated, and
88
+ a new nodeDepth() method has been introduced.
89
+
90
+ ========================================================================
91
+
60
92
  rdoc_options:
61
93
  - --main
62
94
  - README
@@ -81,7 +113,7 @@ rubyforge_project: rubytree
81
113
  rubygems_version: 1.3.5
82
114
  signing_key:
83
115
  specification_version: 3
84
- summary: RubyTree is a Ruby implementation of the generic Tree data structure
116
+ summary: RubyTree is a Ruby implementation of the generic tree data structure
85
117
  test_files:
86
118
  - test/test_binarytree.rb
87
119
  - test/test_tree.rb