rubytree 0.8.2 → 0.8.3
Sign up to get free protection for your applications and to get access to all the features.
- data/.dir-locals.el +5 -0
- data/{API-CHANGES → API-CHANGES.rdoc} +12 -9
- data/{COPYING → COPYING.rdoc} +2 -13
- data/Gemfile +8 -0
- data/Gemfile.lock +28 -0
- data/{History.txt → History.rdoc} +35 -1
- data/{README → README.rdoc} +6 -8
- data/Rakefile +65 -89
- data/TODO.org +174 -0
- data/lib/rubytree.rb +41 -0
- data/lib/tree.rb +195 -133
- data/lib/tree/binarytree.rb +5 -7
- data/lib/tree/tree_deps.rb +41 -0
- data/lib/tree/version.rb +41 -0
- data/test/test_binarytree.rb +1 -2
- data/test/test_rubytree_require.rb +48 -0
- data/test/test_tree.rb +72 -10
- metadata +152 -104
- data/Manifest.txt +0 -12
- data/TODO +0 -57
- data/setup.rb +0 -1585
data/lib/rubytree.rb
ADDED
@@ -0,0 +1,41 @@
|
|
1
|
+
# rubytree.rb - This file is part of the RubyTree package.
|
2
|
+
#
|
3
|
+
|
4
|
+
# = rubytree.rb - Generic implementation of an N-ary tree data structure.
|
5
|
+
#
|
6
|
+
# This file provides an alternative mechanism to require 'tree.rb', in case
|
7
|
+
# there is a conflict with another gem or Ruby package.
|
8
|
+
#
|
9
|
+
# Author:: Anupam Sengupta (anupamsg@gmail.com)
|
10
|
+
#
|
11
|
+
# Copyright (c) 2012 Anupam Sengupta
|
12
|
+
#
|
13
|
+
# All rights reserved.
|
14
|
+
#
|
15
|
+
# Redistribution and use in source and binary forms, with or without modification,
|
16
|
+
# are permitted provided that the following conditions are met:
|
17
|
+
#
|
18
|
+
# - Redistributions of source code must retain the above copyright notice, this
|
19
|
+
# list of conditions and the following disclaimer.
|
20
|
+
#
|
21
|
+
# - Redistributions in binary form must reproduce the above copyright notice, this
|
22
|
+
# list of conditions and the following disclaimer in the documentation and/or
|
23
|
+
# other materials provided with the distribution.
|
24
|
+
#
|
25
|
+
# - Neither the name of the organization nor the names of its contributors may
|
26
|
+
# be used to endorse or promote products derived from this software without
|
27
|
+
# specific prior written permission.
|
28
|
+
#
|
29
|
+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
30
|
+
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
31
|
+
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
32
|
+
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
33
|
+
# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
34
|
+
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
35
|
+
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
36
|
+
# ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
37
|
+
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
38
|
+
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
39
|
+
#
|
40
|
+
|
41
|
+
require "tree.rb"
|
data/lib/tree.rb
CHANGED
@@ -1,7 +1,5 @@
|
|
1
1
|
# tree.rb - This file is part of the RubyTree package.
|
2
2
|
#
|
3
|
-
# $Revision$ by $Author$ on $Date$
|
4
|
-
#
|
5
3
|
# = tree.rb - Generic implementation of an N-ary tree data structure.
|
6
4
|
#
|
7
5
|
# Provides a generic tree data structure with ability to
|
@@ -11,7 +9,7 @@
|
|
11
9
|
# Author:: Anupam Sengupta (anupamsg@gmail.com)
|
12
10
|
#
|
13
11
|
|
14
|
-
# Copyright (c) 2006, 2007, 2008, 2009, 2010, 2011 Anupam Sengupta
|
12
|
+
# Copyright (c) 2006, 2007, 2008, 2009, 2010, 2011, 2012 Anupam Sengupta
|
15
13
|
#
|
16
14
|
# All rights reserved.
|
17
15
|
#
|
@@ -41,37 +39,44 @@
|
|
41
39
|
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
42
40
|
#
|
43
41
|
|
42
|
+
require 'tree/tree_deps'
|
43
|
+
require 'tree/version'
|
44
|
+
|
44
45
|
# This module provides a TreeNode class which is the primary class for representing
|
45
46
|
# nodes in the tree.
|
46
47
|
#
|
47
48
|
# This module also acts as the namespace for all classes in the RubyTree package.
|
48
49
|
module Tree
|
49
50
|
|
50
|
-
# Rubytree Package Version
|
51
|
-
VERSION = '0.8.2'
|
52
|
-
|
53
51
|
# == TreeNode Class Description
|
54
52
|
#
|
55
|
-
# This class models the nodes for an *N-ary* tree data structue. The
|
56
|
-
# and have a place-holder for the node data (i.e.,
|
57
|
-
# names are required to be *unique*
|
53
|
+
# This class models the nodes for an *N-ary* tree data structue. The
|
54
|
+
# nodes are *named* and have a place-holder for the node data (i.e.,
|
55
|
+
# _content_ of the node). The node names are required to be *unique*
|
56
|
+
# within the tree (as the name is implicitly used as an _ID_ within
|
57
|
+
# the data structure).
|
58
58
|
#
|
59
|
-
# The node's _content_ is *not* required to be unique across
|
60
|
-
# can be +nil+ as well.
|
59
|
+
# The node's _content_ is *not* required to be unique across
|
60
|
+
# different nodes in the tree, and can be +nil+ as well.
|
61
61
|
#
|
62
|
-
# The class provides various methods to navigate the tree, traverse
|
63
|
-
# modify contents of the node, change position of the
|
64
|
-
# and to make structural changes to the tree.
|
62
|
+
# The class provides various methods to navigate the tree, traverse
|
63
|
+
# the structure, modify contents of the node, change position of the
|
64
|
+
# node in the tree, and to make structural changes to the tree.
|
65
65
|
#
|
66
|
-
# A node can have any number of *child* nodes attached to it and
|
67
|
-
#
|
68
|
-
#
|
66
|
+
# A node can have any number of *child* nodes attached to it and
|
67
|
+
# hence can be used to create N-ary trees. Access to the child
|
68
|
+
# nodes can be made in order (with the conventional left to right
|
69
|
+
# access), or randomly.
|
69
70
|
#
|
70
|
-
# The node also provides direct access to its *parent* node as well
|
71
|
-
#
|
71
|
+
# The node also provides direct access to its *parent* node as well
|
72
|
+
# as other superior parents in the path to root of the tree. In
|
73
|
+
# addition, a node can also access its *sibling* nodes, if present.
|
72
74
|
#
|
73
|
-
# Note that while this implementation does not _explicitly_ support
|
74
|
-
#
|
75
|
+
# Note that while this implementation does not _explicitly_ support
|
76
|
+
# directed graphs, the class itself makes no restrictions on
|
77
|
+
# associating a node's *content* with multiple nodes in the tree.
|
78
|
+
# However, having duplicate nodes within the structure is likely to
|
79
|
+
# cause unpredictable behavior.
|
75
80
|
#
|
76
81
|
#
|
77
82
|
# == Example
|
@@ -126,28 +131,62 @@ module Tree
|
|
126
131
|
class TreeNode
|
127
132
|
include Enumerable
|
128
133
|
|
134
|
+
# @!attribute [r] name
|
135
|
+
#
|
129
136
|
# Name of this node. Expected to be unique within the tree.
|
137
|
+
#
|
138
|
+
# Note that the name attribute really functions as an *ID* within
|
139
|
+
# the tree structure, and hence the uniqueness constraint is
|
140
|
+
# required.
|
141
|
+
#
|
142
|
+
# This may be changed in the future, but for now it is best to
|
143
|
+
# retain unique names within the tree structure, and use the
|
144
|
+
# +content+ attribute for any non-unique node requirements.
|
145
|
+
#
|
146
|
+
# @see content
|
130
147
|
attr_reader :name
|
131
148
|
|
132
|
-
#
|
149
|
+
# @!attribute [rw] content
|
150
|
+
#
|
151
|
+
# Content of this node. Can be +nil+. Note that there is no
|
152
|
+
# uniqueness constraint related to this attribute.
|
153
|
+
#
|
154
|
+
# @see name
|
133
155
|
attr_accessor :content
|
134
156
|
|
157
|
+
# @!attribute [r] parent
|
158
|
+
#
|
135
159
|
# Parent of this node. Will be +nil+ for a root node.
|
136
160
|
attr_reader :parent
|
137
161
|
|
162
|
+
# @!group Node Creation
|
163
|
+
|
138
164
|
# Creates a new node with a name and optional content.
|
139
165
|
# The node name is expected to be unique within the tree.
|
140
166
|
#
|
141
167
|
# The content can be of any type, and defaults to +nil+.
|
142
168
|
#
|
143
|
-
# @param [Object] name Name of the node.
|
169
|
+
# @param [Object] name Name of the node. Conventional usage is to pass a String
|
170
|
+
# (Integer names may cause *surprises*)
|
144
171
|
# @param [Object] content Content of the node.
|
145
172
|
#
|
146
173
|
# @raise [ArgumentError] Raised if the node name is empty.
|
174
|
+
#
|
175
|
+
# @note If the name is an +Integer+, then the semantics of +TreeNode[]+ can
|
176
|
+
# be surprising, as an +Integer+ parameter to that method normally acts
|
177
|
+
# as an index to the <em>children array</em>, and follows the
|
178
|
+
# <em>zero-based</em> indexing convention.
|
179
|
+
#
|
180
|
+
# @see #[]
|
147
181
|
def initialize(name, content = nil)
|
148
182
|
raise ArgumentError, "Node name HAS to be provided!" if name == nil
|
149
183
|
@name, @content = name, content
|
150
184
|
|
185
|
+
if name.kind_of?(Integer)
|
186
|
+
warn StandardWarning,
|
187
|
+
"Using integer as node name. Semantics of TreeNode[] may not be what you expect! #{name} #{content}"
|
188
|
+
end
|
189
|
+
|
151
190
|
self.set_as_root!
|
152
191
|
@children_hash = Hash.new
|
153
192
|
@children = []
|
@@ -178,6 +217,8 @@ module Tree
|
|
178
217
|
# @see Tree::TreeNode#detached_subtree_copy
|
179
218
|
alias :dup :detached_subtree_copy
|
180
219
|
|
220
|
+
# @!endgroup
|
221
|
+
|
181
222
|
# Returns string representation of the receiver node.
|
182
223
|
# This method is primarily meant for debugging purposes.
|
183
224
|
#
|
@@ -190,7 +231,8 @@ module Tree
|
|
190
231
|
" Total Nodes: #{size()}"
|
191
232
|
end
|
192
233
|
|
193
|
-
#
|
234
|
+
# @!attribute [r] parentage
|
235
|
+
# An array of ancestors of the receiver node in reversed order
|
194
236
|
# (the first element is the immediate parent of the receiver).
|
195
237
|
#
|
196
238
|
# Returns +nil+ if the receiver is a root node.
|
@@ -219,6 +261,8 @@ module Tree
|
|
219
261
|
@parent = parent
|
220
262
|
end
|
221
263
|
|
264
|
+
# @!group Structure Modification
|
265
|
+
|
222
266
|
# Convenience synonym for {Tree::TreeNode#add} method.
|
223
267
|
#
|
224
268
|
# This method allows an easy mechanism to add node hierarchies to the tree
|
@@ -267,7 +311,8 @@ module Tree
|
|
267
311
|
#
|
268
312
|
# @see #<<
|
269
313
|
def add(child, at_index = -1)
|
270
|
-
raise ArgumentError, "Attempting to add a nil node" unless child
|
314
|
+
raise ArgumentError, "Attempting to add a nil node" unless child # Only handles the immediate child scenario
|
315
|
+
raise ArgumentError, "Attempting add node to itself" if self == child
|
271
316
|
raise "Child #{child.name} already added!" if @children_hash.has_key?(child.name)
|
272
317
|
|
273
318
|
if insertion_range.include?(at_index)
|
@@ -281,8 +326,6 @@ module Tree
|
|
281
326
|
return child
|
282
327
|
end
|
283
328
|
|
284
|
-
|
285
|
-
|
286
329
|
# Removes the specified child node from the receiver node.
|
287
330
|
#
|
288
331
|
# This method can also be used for *pruning* a sub-tree, in cases where the removed child node is
|
@@ -346,6 +389,8 @@ module Tree
|
|
346
389
|
@parent = nil
|
347
390
|
end
|
348
391
|
|
392
|
+
# @!endgroup
|
393
|
+
|
349
394
|
# Returns +true+ if the receiver is a root node. Note that
|
350
395
|
# orphaned children will also be reported as root nodes.
|
351
396
|
#
|
@@ -373,10 +418,13 @@ module Tree
|
|
373
418
|
!has_children?
|
374
419
|
end
|
375
420
|
|
376
|
-
#
|
377
|
-
#
|
421
|
+
# @!attribute [rw] children
|
422
|
+
# An array of all the immediate children of the receiver
|
423
|
+
# node. The child nodes are ordered "left-to-right" in the
|
424
|
+
# returned array.
|
378
425
|
#
|
379
|
-
# If a block is given, yields each child node to the block
|
426
|
+
# If a block is given, yields each child node to the block
|
427
|
+
# traversing from left to right.
|
380
428
|
#
|
381
429
|
# @yield [child] Each child is passed to the block, if given
|
382
430
|
# @yieldparam [Tree::TreeNode] child Each child node.
|
@@ -390,24 +438,26 @@ module Tree
|
|
390
438
|
end
|
391
439
|
end
|
392
440
|
|
393
|
-
#
|
394
|
-
#
|
395
|
-
# Will
|
441
|
+
# @!attribute [rw] first_child
|
442
|
+
# First child of the receiver node.
|
443
|
+
# Will be +nil+ if no children are present.
|
396
444
|
#
|
397
445
|
# @return [Tree::TreeNode] The first child, or +nil+ if none is present.
|
398
446
|
def first_child
|
399
447
|
children.first
|
400
448
|
end
|
401
449
|
|
402
|
-
#
|
403
|
-
#
|
404
|
-
# Will
|
450
|
+
# @!attribute [rw] last_child
|
451
|
+
# Last child of the receiver node.
|
452
|
+
# Will be +nil+ if no children are present.
|
405
453
|
#
|
406
454
|
# @return [Tree::TreeNode] The last child, or +nil+ if none is present.
|
407
455
|
def last_child
|
408
456
|
children.last
|
409
457
|
end
|
410
458
|
|
459
|
+
# @!group Tree Traversal
|
460
|
+
|
411
461
|
# Traverses each node (including the receiver node) of the (sub)tree rooted at this node
|
412
462
|
# by yielding the nodes to the specified block.
|
413
463
|
#
|
@@ -467,55 +517,77 @@ module Tree
|
|
467
517
|
# @see #each
|
468
518
|
# @see #breadth_each
|
469
519
|
def each_leaf &block
|
470
|
-
|
520
|
+
if block_given?
|
521
|
+
self.each { |node| yield(node) if node.is_leaf? }
|
522
|
+
else
|
523
|
+
self.select { |node| node.is_leaf?}
|
524
|
+
end
|
471
525
|
end
|
472
526
|
|
473
527
|
# Returns the requested node from the set of immediate children.
|
474
528
|
#
|
475
|
-
# If the argument is
|
476
|
-
# the argument as the
|
529
|
+
# - If the +name+ argument is an _Integer_, then the in-sequence
|
530
|
+
# array of children is accessed using the argument as the
|
531
|
+
# *index* (zero-based). However, if the second _optional_
|
532
|
+
# +num_as_name+ argument is +true+, then the +name+ is used
|
533
|
+
# literally as a name, and *NOT* as an *index*
|
477
534
|
#
|
478
|
-
# If the argument is *NOT*
|
535
|
+
# - If the +name+ argument is *NOT* an _Integer_, then it is taken to
|
536
|
+
# be the *name* of the child node to be returned.
|
479
537
|
#
|
480
|
-
#
|
538
|
+
# If a non-+Integer+ +name+ is passed, and the +num_as_name+
|
539
|
+
# parameter is also +true+, then a warning is thrown (as this is a
|
540
|
+
# redundant use of the +num_as_name+ flag.)
|
481
541
|
#
|
482
|
-
# @param [String|Number] name_or_index Name of the child, or its
|
542
|
+
# @param [String|Number] name_or_index Name of the child, or its
|
543
|
+
# positional index in the array of child nodes.
|
483
544
|
#
|
484
|
-
# @
|
485
|
-
#
|
545
|
+
# @param [Boolean] num_as_name Whether to treat the +Integer+
|
546
|
+
# +name+ argument as an actual name, and *NOT* as an _index_ to
|
547
|
+
# the children array.
|
486
548
|
#
|
487
|
-
# @
|
549
|
+
# @return [Tree::TreeNode] the requested child node. If the index
|
550
|
+
# in not in range, or the name is not present, then a +nil+
|
551
|
+
# is returned.
|
552
|
+
#
|
553
|
+
# @note The use of +Integer+ names is allowed by using the optional +num_as_name+ flag.
|
554
|
+
#
|
555
|
+
# @raise [ArgumentError] Raised if the +name_or_index+ argument is +nil+.
|
488
556
|
#
|
489
557
|
# @see #add
|
490
|
-
|
558
|
+
# @see #initialize
|
559
|
+
def [](name_or_index, num_as_name=false)
|
491
560
|
raise ArgumentError, "Name_or_index needs to be provided!" if name_or_index == nil
|
492
561
|
|
493
|
-
if name_or_index.kind_of?(Integer)
|
562
|
+
if name_or_index.kind_of?(Integer) and not num_as_name
|
494
563
|
@children[name_or_index]
|
495
564
|
else
|
565
|
+
if num_as_name and not name_or_index.kind_of?(Integer)
|
566
|
+
warn StandardWarning, "Redundant use of the `num_as_name` flag for non-integer node name"
|
567
|
+
end
|
496
568
|
@children_hash[name_or_index]
|
497
569
|
end
|
498
570
|
end
|
499
571
|
|
500
|
-
#
|
572
|
+
# @!endgroup
|
573
|
+
|
574
|
+
# @!attribute [r] size
|
575
|
+
# Total number of nodes in this (sub)tree, including the receiver node.
|
501
576
|
#
|
502
577
|
# Size of the tree is defined as:
|
503
578
|
#
|
504
579
|
# Size:: Total number nodes in the subtree including the receiver node.
|
505
580
|
#
|
506
|
-
# @return [
|
581
|
+
# @return [Integer] Total number of nodes in this (sub)tree.
|
507
582
|
def size
|
508
583
|
@children.inject(1) {|sum, node| sum + node.size}
|
509
584
|
end
|
510
585
|
|
511
586
|
# Convenience synonym for {Tree::TreeNode#size}.
|
512
587
|
#
|
513
|
-
# @todo The semantic of length is probably unclear. Should return the node depth instead
|
514
|
-
# to reflect the path length.
|
515
|
-
#
|
516
588
|
# @deprecated This method name is ambiguous and may be removed. Use TreeNode#size instead.
|
517
589
|
#
|
518
|
-
# @return [
|
590
|
+
# @return [Integer] The total number of nodes in this (sub)tree.
|
519
591
|
# @see #size
|
520
592
|
def length
|
521
593
|
size()
|
@@ -523,7 +595,7 @@ module Tree
|
|
523
595
|
|
524
596
|
# Pretty prints the (sub)tree rooted at the receiver node.
|
525
597
|
#
|
526
|
-
# @param [
|
598
|
+
# @param [Integer] level The indentation level (4 spaces) to start with.
|
527
599
|
def print_tree(level = 0)
|
528
600
|
if is_root?
|
529
601
|
print "*"
|
@@ -540,11 +612,9 @@ module Tree
|
|
540
612
|
children { |child| child.print_tree(level + 1)}
|
541
613
|
end
|
542
614
|
|
543
|
-
#
|
544
|
-
#
|
545
|
-
#
|
546
|
-
#
|
547
|
-
# @todo We should perhaps return nil as root's root.
|
615
|
+
# @!attribute [rw] root
|
616
|
+
# root node for the (sub)tree to which the receiver node belongs.
|
617
|
+
# A root node's root is itself.
|
548
618
|
#
|
549
619
|
# @return [Tree::TreeNode] Root of the (sub)tree.
|
550
620
|
def root
|
@@ -553,15 +623,13 @@ module Tree
|
|
553
623
|
root
|
554
624
|
end
|
555
625
|
|
556
|
-
#
|
626
|
+
# @!attribute [rw] first_sibling
|
627
|
+
# First sibling of the receiver node. If this is the root node, then returns
|
557
628
|
# itself.
|
558
629
|
#
|
559
630
|
# 'First' sibling is defined as follows:
|
560
631
|
# First sibling:: The left-most child of the receiver's parent, which may be the receiver itself
|
561
632
|
#
|
562
|
-
# @todo Fix the inconsistency of returning root as its first sibling, and returning
|
563
|
-
# a +nil+ array for siblings of the node.
|
564
|
-
#
|
565
633
|
# @return [Tree::TreeNode] The first sibling node.
|
566
634
|
#
|
567
635
|
# @see #is_first_sibling?
|
@@ -580,15 +648,13 @@ module Tree
|
|
580
648
|
first_sibling == self
|
581
649
|
end
|
582
650
|
|
583
|
-
#
|
651
|
+
# @!attribute [rw] last_sibling
|
652
|
+
# Last sibling of the receiver node. If this is the root node, then returns
|
584
653
|
# itself.
|
585
654
|
#
|
586
655
|
# 'Last' sibling is defined as follows:
|
587
656
|
# Last sibling:: The right-most child of the receiver's parent, which may be the receiver itself
|
588
657
|
#
|
589
|
-
# @todo Fix the inconsistency of returning root as its last sibling, and returning
|
590
|
-
# a +nil+ array for siblings of the node.
|
591
|
-
#
|
592
658
|
# @return [Tree::TreeNode] The last sibling node.
|
593
659
|
#
|
594
660
|
# @see #is_last_sibling?
|
@@ -607,16 +673,12 @@ module Tree
|
|
607
673
|
last_sibling == self
|
608
674
|
end
|
609
675
|
|
610
|
-
#
|
676
|
+
# @!attribute [rw] siblings
|
677
|
+
# An array of siblings for the receiver node. The receiver node is excluded.
|
611
678
|
#
|
612
679
|
# If a block is provided, yields each of the sibling nodes to the block.
|
613
680
|
# The root always has +nil+ siblings.
|
614
681
|
#
|
615
|
-
# @todo Fix the inconsistency of returning root as its own first/last sibling, and returning
|
616
|
-
# a +nil+ array for siblings of the same root node.
|
617
|
-
# @todo Also fix the inconsistency of returning +nil+ for a root node, and an empty array for nodes
|
618
|
-
# which have no siblings.
|
619
|
-
#
|
620
682
|
# @yield [sibling] Each sibling is passed to the block.
|
621
683
|
# @yieldparam [Tree::TreeNode] sibling Each sibling node.
|
622
684
|
#
|
@@ -625,7 +687,7 @@ module Tree
|
|
625
687
|
# @see #first_sibling
|
626
688
|
# @see #last_sibling
|
627
689
|
def siblings
|
628
|
-
return
|
690
|
+
return [] if is_root?
|
629
691
|
|
630
692
|
if block_given?
|
631
693
|
parent.children.each { |sibling| yield sibling if sibling != self }
|
@@ -647,7 +709,8 @@ module Tree
|
|
647
709
|
is_root? ? true : parent.children.size == 1
|
648
710
|
end
|
649
711
|
|
650
|
-
#
|
712
|
+
# @!attribute [rw] next_sibling
|
713
|
+
# Next sibling for the receiver node.
|
651
714
|
# The 'next' node is defined as the node to right of the receiver node.
|
652
715
|
#
|
653
716
|
# Will return +nil+ if no subsequent node is present, or if the receiver is a root node.
|
@@ -663,7 +726,8 @@ module Tree
|
|
663
726
|
parent.children.at(myidx + 1) if myidx
|
664
727
|
end
|
665
728
|
|
666
|
-
#
|
729
|
+
# @!attribute [rw] previous_sibling
|
730
|
+
# Previous sibling of the receiver node.
|
667
731
|
# 'Previous' node is defined to be the node to left of the receiver node.
|
668
732
|
#
|
669
733
|
# Will return +nil+ if no predecessor node is present, or if the receiver is a root node.
|
@@ -685,7 +749,7 @@ module Tree
|
|
685
749
|
#
|
686
750
|
# @param [Tree::TreeNode] other The other node to compare against.
|
687
751
|
#
|
688
|
-
# @return [
|
752
|
+
# @return [Integer] +1 if this node is a 'successor', 0 if equal and -1 if this node is a 'predecessor'.
|
689
753
|
def <=>(other)
|
690
754
|
return +1 if other == nil
|
691
755
|
self.name <=> other.name
|
@@ -735,19 +799,18 @@ module Tree
|
|
735
799
|
end
|
736
800
|
end
|
737
801
|
|
738
|
-
# Creates a JSON
|
739
|
-
# available, or else the operation fails with a warning message.
|
802
|
+
# Creates a JSON ready Hash for the #to_json method.
|
740
803
|
#
|
741
|
-
# @author
|
742
|
-
# @since 0.
|
804
|
+
# @author Eric Cline (https://github.com/escline)
|
805
|
+
# @since 0.8.3
|
743
806
|
#
|
744
|
-
# @return
|
807
|
+
# @return A hash based representation of the JSON
|
745
808
|
#
|
746
|
-
#
|
747
|
-
#
|
748
|
-
|
749
|
-
|
750
|
-
|
809
|
+
# Rails uses JSON in ActiveSupport, and all Rails JSON encoding goes through as_json
|
810
|
+
#
|
811
|
+
# @see Tree::TreeNode.to_json
|
812
|
+
# @see http://stackoverflow.com/a/6880638/273808
|
813
|
+
def as_json(options = {})
|
751
814
|
|
752
815
|
json_hash = {
|
753
816
|
"name" => name,
|
@@ -759,11 +822,24 @@ module Tree
|
|
759
822
|
json_hash["children"] = children
|
760
823
|
end
|
761
824
|
|
762
|
-
return json_hash
|
825
|
+
return json_hash
|
763
826
|
|
764
|
-
|
765
|
-
|
766
|
-
|
827
|
+
end
|
828
|
+
|
829
|
+
# Creates a JSON representation of this node including all it's children. This requires the JSON gem to be
|
830
|
+
# available, or else the operation fails with a warning message.
|
831
|
+
# Uses the Hash output of as_json method, defined above.
|
832
|
+
#
|
833
|
+
# @author Dirk Breuer (http://github.com/railsbros-dirk)
|
834
|
+
# @since 0.7.0
|
835
|
+
#
|
836
|
+
# @return The JSON representation of this subtree.
|
837
|
+
#
|
838
|
+
# @see Tree::TreeNode.json_create
|
839
|
+
# @see Tree::TreeNode.as_json
|
840
|
+
# @see http://flori.github.com/json
|
841
|
+
def to_json(*a)
|
842
|
+
as_json.to_json(*a)
|
767
843
|
end
|
768
844
|
|
769
845
|
# Helper method to create a Tree::TreeNode instance from the JSON hash representation. Note that this method should
|
@@ -783,35 +859,33 @@ module Tree
|
|
783
859
|
# @see #to_json
|
784
860
|
# @see http://flori.github.com/json
|
785
861
|
def self.json_create(json_hash)
|
786
|
-
begin
|
787
|
-
require 'json'
|
788
862
|
|
789
|
-
|
863
|
+
node = new(json_hash["name"], json_hash["content"])
|
790
864
|
|
791
|
-
|
792
|
-
|
793
|
-
|
865
|
+
json_hash["children"].each do |child|
|
866
|
+
node << child
|
867
|
+
end if json_hash["children"]
|
868
|
+
|
869
|
+
return node
|
794
870
|
|
795
|
-
return node
|
796
|
-
rescue LoadError => e
|
797
|
-
warn "The JSON gem couldn't be loaded. Due to this we cannot serialize the tree to a JSON representation."
|
798
|
-
end
|
799
871
|
end
|
800
872
|
|
801
|
-
#
|
873
|
+
# @!attribute [r] node_height
|
874
|
+
# Height of the (sub)tree from the receiver node. Height of a node is defined as:
|
802
875
|
#
|
803
876
|
# Height:: Length of the longest downward path to a leaf from the node.
|
804
877
|
#
|
805
878
|
# - Height from a root node is height of the entire tree.
|
806
879
|
# - The height of a leaf node is zero.
|
807
880
|
#
|
808
|
-
# @return [
|
881
|
+
# @return [Integer] Height of the node.
|
809
882
|
def node_height
|
810
883
|
return 0 if is_leaf?
|
811
884
|
1 + @children.collect { |child| child.node_height }.max
|
812
885
|
end
|
813
886
|
|
814
|
-
#
|
887
|
+
# @!attribute [r] node_depth
|
888
|
+
# Depth of the receiver node in its tree. Depth of a node is defined as:
|
815
889
|
#
|
816
890
|
# Depth:: Length of the node's path to its root. Depth of a root node is zero.
|
817
891
|
#
|
@@ -820,7 +894,7 @@ module Tree
|
|
820
894
|
#
|
821
895
|
# 'level' is an alias for this method.
|
822
896
|
#
|
823
|
-
# @return [
|
897
|
+
# @return [Integer] Depth of this node.
|
824
898
|
def node_depth
|
825
899
|
return 0 if is_root?
|
826
900
|
1 + parent.node_depth
|
@@ -838,74 +912,62 @@ module Tree
|
|
838
912
|
# For correct and conventional behavior, please use {Tree::TreeNode#node_depth} and
|
839
913
|
# {Tree::TreeNode#node_height} methods instead.
|
840
914
|
#
|
841
|
-
# @return [
|
915
|
+
# @return [Integer] depth of the node.
|
842
916
|
# @deprecated This method returns an incorrect value. Use the 'node_depth' method instead.
|
843
917
|
#
|
844
918
|
# @see #node_depth
|
845
919
|
def depth
|
846
|
-
|
847
|
-
require 'structured_warnings' # To enable a nice way of deprecating of the depth method.
|
848
|
-
warn DeprecatedMethodWarning, 'This method is deprecated. Please use node_depth() or node_height() instead (bug # 22535)'
|
849
|
-
rescue LoadError
|
850
|
-
# Oh well. Will use the standard Kernel#warn. Behavior will be identical.
|
851
|
-
warn 'Tree::TreeNode#depth() method is deprecated. Please use node_depth() or node_height() instead (bug # 22535)'
|
852
|
-
end
|
920
|
+
warn DeprecatedMethodWarning, 'This method is deprecated. Please use node_depth() or node_height() instead (bug # 22535)'
|
853
921
|
|
854
922
|
return 1 if is_leaf?
|
855
923
|
1 + @children.collect { |child| child.depth }.max
|
856
924
|
end
|
857
925
|
|
858
926
|
# Allow the deprecated CamelCase method names. Display a warning.
|
927
|
+
# :nodoc:
|
859
928
|
def method_missing(meth, *args, &blk)
|
860
929
|
if self.respond_to?(new_method_name = underscore(meth))
|
861
|
-
|
862
|
-
|
863
|
-
warn DeprecatedMethodWarning, "The camelCased methods are deprecated. Please use #{new_method_name} instead of #{meth}"
|
864
|
-
|
865
|
-
rescue LoadError
|
866
|
-
# Oh well. Will use the standard Kernel#warn. Behavior will be identical.
|
867
|
-
warn "Tree::TreeNode##{meth}() method is deprecated. Please use #{new_method_name} instead."
|
868
|
-
|
869
|
-
ensure # Invoke the method now.
|
870
|
-
return send(new_method_name, *args, &blk)
|
871
|
-
end
|
872
|
-
|
930
|
+
warn DeprecatedMethodWarning, "The camelCased methods are deprecated. Please use #{new_method_name} instead of #{meth}"
|
931
|
+
return send(new_method_name, *args, &blk)
|
873
932
|
else
|
874
933
|
super
|
875
934
|
end
|
876
935
|
end
|
877
936
|
|
878
|
-
#
|
937
|
+
# @!attribute [r] breadth
|
938
|
+
# Breadth of the tree at the receiver node's level.
|
879
939
|
# A single node without siblings has a breadth of 1.
|
880
940
|
#
|
881
941
|
# Breadth is defined to be:
|
882
942
|
# Breadth:: Number of sibling nodes to this node + 1 (this node itself),
|
883
943
|
# i.e., the number of children the parent of this node has.
|
884
944
|
#
|
885
|
-
# @return [
|
945
|
+
# @return [Integer] breadth of the node's level.
|
886
946
|
def breadth
|
887
947
|
is_root? ? 1 : parent.children.size
|
888
948
|
end
|
889
949
|
|
890
|
-
#
|
950
|
+
# @!attribute [r] in_degree
|
951
|
+
# The incoming edge-count of the receiver node.
|
891
952
|
#
|
892
953
|
# In-degree is defined as:
|
893
|
-
# In-degree::
|
954
|
+
# In-degree:: Number of edges arriving at the node (0 for root, 1 for all other nodes)
|
894
955
|
#
|
895
956
|
# - In-degree = 0 for a root or orphaned node
|
896
957
|
# - In-degree = 1 for a node which has a parent
|
897
958
|
#
|
898
|
-
# @return [
|
959
|
+
# @return [Integer] The in-degree of this node.
|
899
960
|
def in_degree
|
900
961
|
is_root? ? 0 : 1
|
901
962
|
end
|
902
963
|
|
903
|
-
#
|
964
|
+
# @!attribute [r] out_degree
|
965
|
+
# The outgoing edge-count of the receiver node.
|
904
966
|
#
|
905
967
|
# Out-degree is defined as:
|
906
|
-
# Out-degree::
|
968
|
+
# Out-degree:: Number of edges leaving the node (zero for leafs)
|
907
969
|
#
|
908
|
-
# @return [
|
970
|
+
# @return [Integer] The out-degree of this node.
|
909
971
|
def out_degree
|
910
972
|
is_leaf? ? 0 : children.size
|
911
973
|
end
|