rubytree 0.8.3 → 0.9.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/API-CHANGES.rdoc +51 -20
- data/Gemfile +5 -1
- data/Gemfile.lock +14 -13
- data/History.rdoc +110 -42
- data/LICENSE.md +37 -0
- data/README.md +276 -0
- data/Rakefile +53 -28
- data/TAGS +218 -0
- data/TODO.org +114 -42
- data/examples/example_basic.rb +53 -0
- data/lib/tree.rb +357 -529
- data/lib/tree/binarytree.rb +76 -36
- data/lib/tree/utils/camel_case_method_handler.rb +78 -0
- data/lib/tree/utils/json_converter.rb +125 -0
- data/lib/tree/utils/metrics_methods.rb +172 -0
- data/lib/tree/utils/tree_merge_handler.rb +118 -0
- data/lib/tree/utils/utils.rb +41 -0
- data/lib/tree/version.rb +3 -3
- data/test/test_binarytree.rb +46 -1
- data/test/test_subclassed_node.rb +70 -0
- data/test/test_thread_and_fiber.rb +88 -0
- data/test/test_tree.rb +209 -35
- metadata +85 -82
- data/.dir-locals.el +0 -5
- data/COPYING.rdoc +0 -32
- data/README.rdoc +0 -219
data/lib/tree/binarytree.rb
CHANGED
@@ -8,7 +8,7 @@
|
|
8
8
|
# Author:: Anupam Sengupta (anupamsg@gmail.com)
|
9
9
|
#
|
10
10
|
|
11
|
-
# Copyright (c) 2007, 2008, 2009, 2010, 2012 Anupam Sengupta
|
11
|
+
# Copyright (c) 2007, 2008, 2009, 2010, 2012, 2013 Anupam Sengupta
|
12
12
|
#
|
13
13
|
# All rights reserved.
|
14
14
|
#
|
@@ -51,21 +51,7 @@ module Tree
|
|
51
51
|
#
|
52
52
|
class BinaryTreeNode < TreeNode
|
53
53
|
|
54
|
-
#
|
55
|
-
#
|
56
|
-
# The child nodes are added in the order of addition, i.e., the first child added becomes the left node, and the
|
57
|
-
# second child added will be the second node.
|
58
|
-
#
|
59
|
-
# If only one child is present, then this will be the left child.
|
60
|
-
#
|
61
|
-
# @param [Tree::BinaryTreeNode] child The child to add.
|
62
|
-
#
|
63
|
-
# @raise [ArgumentError] This exception is raised if two children are already present.
|
64
|
-
def add(child)
|
65
|
-
raise ArgumentError, "Already has two child nodes" if @children.size == 2
|
66
|
-
|
67
|
-
super(child)
|
68
|
-
end
|
54
|
+
# @!group Core Attributes
|
69
55
|
|
70
56
|
# @!attribute [rw] left_child
|
71
57
|
# Left child of the receiver node. Note that left Child == first Child.
|
@@ -89,6 +75,78 @@ module Tree
|
|
89
75
|
children[1]
|
90
76
|
end
|
91
77
|
|
78
|
+
# @!attribute is_left_child?
|
79
|
+
# +true+ if the receiver node is the left child of its parent.
|
80
|
+
# Always returns +false+ if it is a root node.
|
81
|
+
#
|
82
|
+
# @return [Boolean] +true+ if this is the left child of its parent.
|
83
|
+
def is_left_child?
|
84
|
+
return false if is_root?
|
85
|
+
self == parent.left_child
|
86
|
+
end
|
87
|
+
|
88
|
+
# @!attribute [r] is_right_child?
|
89
|
+
# +true+ if the receiver node is the right child of its parent.
|
90
|
+
# Always returns +false+ if it is a root node.
|
91
|
+
#
|
92
|
+
# @return [Boolean] +true+ if this is the right child of its parent.
|
93
|
+
def is_right_child?
|
94
|
+
return false if is_root?
|
95
|
+
self == parent.right_child
|
96
|
+
end
|
97
|
+
|
98
|
+
# @!group Structure Modification
|
99
|
+
|
100
|
+
# Adds the specified child node to the receiver node. The child node's parent is set to be the receiver.
|
101
|
+
#
|
102
|
+
# The child nodes are added in the order of addition, i.e., the first child added becomes the left node, and the
|
103
|
+
# second child added will be the second node.
|
104
|
+
#
|
105
|
+
# If only one child is present, then this will be the left child.
|
106
|
+
#
|
107
|
+
# @param [Tree::BinaryTreeNode] child The child to add.
|
108
|
+
#
|
109
|
+
# @raise [ArgumentError] This exception is raised if two children are already present.
|
110
|
+
def add(child)
|
111
|
+
raise ArgumentError, "Already has two child nodes" if @children.size == 2
|
112
|
+
|
113
|
+
super(child)
|
114
|
+
end
|
115
|
+
|
116
|
+
# Performs inorder traversal (including this node).
|
117
|
+
#
|
118
|
+
# @yieldparam node [Tree::BinaryTreeNode] Each node (in-order).
|
119
|
+
#
|
120
|
+
# @return [Tree::BinaryTreeNode] This node, if a block is given
|
121
|
+
# @return [Enumerator] An enumerator on this tree, if a block is *not* given
|
122
|
+
#
|
123
|
+
# @since 0.9.0
|
124
|
+
#
|
125
|
+
# @see #each
|
126
|
+
# @see #preordered_each
|
127
|
+
# @see #postordered_each
|
128
|
+
def inordered_each(&block)
|
129
|
+
|
130
|
+
return self.to_enum unless block_given?
|
131
|
+
|
132
|
+
node_stack = []
|
133
|
+
current_node = self
|
134
|
+
|
135
|
+
until node_stack.empty? and current_node == nil
|
136
|
+
if current_node
|
137
|
+
node_stack.push(current_node)
|
138
|
+
current_node = current_node.left_child
|
139
|
+
else
|
140
|
+
current_node = node_stack.pop()
|
141
|
+
yield current_node
|
142
|
+
current_node = current_node.right_child
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
return self if block_given?
|
147
|
+
|
148
|
+
end
|
149
|
+
|
92
150
|
# A protected method to allow insertion of child nodes at the specified location.
|
93
151
|
# Note that this method allows insertion of +nil+ nodes.
|
94
152
|
#
|
@@ -107,6 +165,8 @@ module Tree
|
|
107
165
|
child
|
108
166
|
end
|
109
167
|
|
168
|
+
protected :set_child_at
|
169
|
+
|
110
170
|
# Sets the left child of the receiver node. If a previous child existed, it is replaced.
|
111
171
|
#
|
112
172
|
# @param [Tree::BinaryTreeNode] child The child to add as the left-side node.
|
@@ -131,31 +191,11 @@ module Tree
|
|
131
191
|
set_child_at child, 1
|
132
192
|
end
|
133
193
|
|
134
|
-
# Returns +true+ if the receiver node is the left child of its parent.
|
135
|
-
# Always returns +false+ if it is a root node.
|
136
|
-
#
|
137
|
-
# @return [Boolean] +true+ if this is the left child of its parent.
|
138
|
-
def is_left_child?
|
139
|
-
return false if is_root?
|
140
|
-
self == parent.left_child
|
141
|
-
end
|
142
|
-
|
143
|
-
# Returns +true+ if the receiver node is the right child of its parent.
|
144
|
-
# Always returns +false+ if it is a root node.
|
145
|
-
#
|
146
|
-
# @return [Boolean] +true+ if this is the right child of its parent.
|
147
|
-
def is_right_child?
|
148
|
-
return false if is_root?
|
149
|
-
self == parent.right_child
|
150
|
-
end
|
151
|
-
|
152
194
|
# Swaps the left and right child nodes of the receiver node with each other.
|
153
195
|
def swap_children
|
154
196
|
self.left_child, self.right_child = self.right_child, self.left_child
|
155
197
|
end
|
156
198
|
|
157
|
-
protected :set_child_at
|
158
|
-
|
159
199
|
end
|
160
200
|
|
161
201
|
end
|
@@ -0,0 +1,78 @@
|
|
1
|
+
# camel_case_methods.rb - This file is part of the RubyTree package.
|
2
|
+
#
|
3
|
+
# = camel_case_methods.rb - Provides conversion from CamelCase to snake_case.
|
4
|
+
#
|
5
|
+
# Author:: Anupam Sengupta (anupamsg@gmail.com)
|
6
|
+
#
|
7
|
+
# Time-stamp: <2013-12-31 20:48:13 anupam>
|
8
|
+
#
|
9
|
+
# Copyright (C) 2012, 2013 Anupam Sengupta <anupamsg@gmail.com>
|
10
|
+
#
|
11
|
+
# All rights reserved.
|
12
|
+
#
|
13
|
+
# Redistribution and use in source and binary forms, with or without modification,
|
14
|
+
# are permitted provided that the following conditions are met:
|
15
|
+
#
|
16
|
+
# - Redistributions of source code must retain the above copyright notice, this
|
17
|
+
# list of conditions and the following disclaimer.
|
18
|
+
#
|
19
|
+
# - Redistributions in binary form must reproduce the above copyright notice, this
|
20
|
+
# list of conditions and the following disclaimer in the documentation and/or
|
21
|
+
# other materials provided with the distribution.
|
22
|
+
#
|
23
|
+
# - Neither the name of the organization nor the names of its contributors may
|
24
|
+
# be used to endorse or promote products derived from this software without
|
25
|
+
# specific prior written permission.
|
26
|
+
#
|
27
|
+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
28
|
+
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
29
|
+
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
30
|
+
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
31
|
+
# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
32
|
+
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
33
|
+
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
34
|
+
# ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
35
|
+
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
36
|
+
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
37
|
+
#
|
38
|
+
|
39
|
+
require 'structured_warnings'
|
40
|
+
|
41
|
+
module Tree::Utils
|
42
|
+
# Provides utility functions to handle CamelCase methods, and redirect
|
43
|
+
# invocation of such methods to the snake_case equivalents.
|
44
|
+
module CamelCaseMethodHandler
|
45
|
+
def self.included(base)
|
46
|
+
# @!visibility private
|
47
|
+
# Allow the deprecated CamelCase method names. Display a warning.
|
48
|
+
# :nodoc:
|
49
|
+
def method_missing(meth, *args, &blk)
|
50
|
+
if self.respond_to?(new_method_name = to_snake_case(meth))
|
51
|
+
warn DeprecatedMethodWarning,
|
52
|
+
"The camelCased methods are deprecated. Please use #{new_method_name} instead of #{meth}"
|
53
|
+
return send(new_method_name, *args, &blk)
|
54
|
+
else
|
55
|
+
super
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
private
|
60
|
+
|
61
|
+
# @!visibility private
|
62
|
+
# Convert a CamelCasedWord to a underscore separated camel_cased_word.
|
63
|
+
#
|
64
|
+
# @param [String] camel_cased_word The word to be converted to snake_case.
|
65
|
+
# @return [String] the snake_cased_word.
|
66
|
+
def to_snake_case(camel_cased_word)
|
67
|
+
word = camel_cased_word.to_s.dup
|
68
|
+
word.gsub!(/::/, '/')
|
69
|
+
word.gsub!(/([A-Z]+)([A-Z][a-z])/,'\1_\2')
|
70
|
+
word.gsub!(/([a-z\d])([A-Z])/,'\1_\2')
|
71
|
+
word.tr!("-", "_")
|
72
|
+
word.downcase!
|
73
|
+
word
|
74
|
+
end
|
75
|
+
|
76
|
+
end # self.included
|
77
|
+
end
|
78
|
+
end
|
@@ -0,0 +1,125 @@
|
|
1
|
+
# json.rb - This file is part of the RubyTree package.
|
2
|
+
#
|
3
|
+
# = json.rb - Provides conversion to and from JSON.
|
4
|
+
#
|
5
|
+
# Author:: Anupam Sengupta (anupamsg@gmail.com)
|
6
|
+
#
|
7
|
+
# Time-stamp: <2013-12-31 21:57:42 anupam>
|
8
|
+
#
|
9
|
+
# Copyright (C) 2012, 2013 Anupam Sengupta <anupamsg@gmail.com>
|
10
|
+
#
|
11
|
+
# All rights reserved.
|
12
|
+
#
|
13
|
+
# Redistribution and use in source and binary forms, with or without modification,
|
14
|
+
# are permitted provided that the following conditions are met:
|
15
|
+
#
|
16
|
+
# - Redistributions of source code must retain the above copyright notice, this
|
17
|
+
# list of conditions and the following disclaimer.
|
18
|
+
#
|
19
|
+
# - Redistributions in binary form must reproduce the above copyright notice, this
|
20
|
+
# list of conditions and the following disclaimer in the documentation and/or
|
21
|
+
# other materials provided with the distribution.
|
22
|
+
#
|
23
|
+
# - Neither the name of the organization nor the names of its contributors may
|
24
|
+
# be used to endorse or promote products derived from this software without
|
25
|
+
# specific prior written permission.
|
26
|
+
#
|
27
|
+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
28
|
+
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
29
|
+
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
30
|
+
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
31
|
+
# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
32
|
+
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
33
|
+
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
34
|
+
# ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
35
|
+
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
36
|
+
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
37
|
+
|
38
|
+
require 'json'
|
39
|
+
|
40
|
+
# Provides utility methods to convert a {Tree::TreeNode} to and from
|
41
|
+
# JSON[http://flori.github.com/json/].
|
42
|
+
module Tree::Utils::JSONConverter
|
43
|
+
|
44
|
+
def self.included(base)
|
45
|
+
base.extend(ClassMethods)
|
46
|
+
end
|
47
|
+
|
48
|
+
# @!group Converting to/from JSON
|
49
|
+
|
50
|
+
# Creates a JSON ready Hash for the #to_json method.
|
51
|
+
#
|
52
|
+
# @author Eric Cline (https://github.com/escline)
|
53
|
+
# @since 0.8.3
|
54
|
+
#
|
55
|
+
# @return A hash based representation of the JSON
|
56
|
+
#
|
57
|
+
# Rails uses JSON in ActiveSupport, and all Rails JSON encoding goes through +as_json+.
|
58
|
+
#
|
59
|
+
# @see #to_json
|
60
|
+
# @see http://stackoverflow.com/a/6880638/273808
|
61
|
+
def as_json(options = {})
|
62
|
+
|
63
|
+
json_hash = {
|
64
|
+
"name" => name,
|
65
|
+
"content" => content,
|
66
|
+
JSON.create_id => self.class.name
|
67
|
+
}
|
68
|
+
|
69
|
+
if has_children?
|
70
|
+
json_hash["children"] = children
|
71
|
+
end
|
72
|
+
|
73
|
+
return json_hash
|
74
|
+
|
75
|
+
end
|
76
|
+
|
77
|
+
# Creates a JSON representation of this node including all it's children.
|
78
|
+
# This requires the JSON gem to be available, or else the operation fails with
|
79
|
+
# a warning message. Uses the Hash output of #as_json method.
|
80
|
+
#
|
81
|
+
# @author Dirk Breuer (http://github.com/railsbros-dirk)
|
82
|
+
# @since 0.7.0
|
83
|
+
#
|
84
|
+
# @return The JSON representation of this subtree.
|
85
|
+
#
|
86
|
+
# @see ClassMethods#json_create
|
87
|
+
# @see #as_json
|
88
|
+
# @see http://flori.github.com/json
|
89
|
+
def to_json(*a)
|
90
|
+
as_json.to_json(*a)
|
91
|
+
end
|
92
|
+
|
93
|
+
# ClassMethods for the {JSONConverter} module. Will become class methods in the +include+ target.
|
94
|
+
module ClassMethods
|
95
|
+
# Helper method to create a Tree::TreeNode instance from the JSON hash
|
96
|
+
# representation. Note that this method should *NOT* be called directly.
|
97
|
+
# Instead, to convert the JSON hash back to a tree, do:
|
98
|
+
#
|
99
|
+
# tree = JSON.parse(the_json_hash)
|
100
|
+
#
|
101
|
+
# This operation requires the {JSON gem}[http://flori.github.com/json/] to
|
102
|
+
# be available, or else the operation fails with a warning message.
|
103
|
+
#
|
104
|
+
# @author Dirk Breuer (http://github.com/railsbros-dirk)
|
105
|
+
# @since 0.7.0
|
106
|
+
#
|
107
|
+
# @param [Hash] json_hash The JSON hash to convert from.
|
108
|
+
#
|
109
|
+
# @return [Tree::TreeNode] The created tree.
|
110
|
+
#
|
111
|
+
# @see #to_json
|
112
|
+
# @see http://flori.github.com/json
|
113
|
+
def json_create(json_hash)
|
114
|
+
|
115
|
+
node = new(json_hash["name"], json_hash["content"])
|
116
|
+
|
117
|
+
json_hash["children"].each do |child|
|
118
|
+
node << child
|
119
|
+
end if json_hash["children"]
|
120
|
+
|
121
|
+
return node
|
122
|
+
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
@@ -0,0 +1,172 @@
|
|
1
|
+
# metrics_methods.rb - This file is part of the RubyTree package.
|
2
|
+
#
|
3
|
+
# = metrics_methods.rb - Provides methods for various tree measurements
|
4
|
+
#
|
5
|
+
# Author:: Anupam Sengupta (anupamsg@gmail.com)
|
6
|
+
#
|
7
|
+
# Time-stamp: <2013-12-31 21:45:35 anupam>
|
8
|
+
#
|
9
|
+
# Copyright (C) 2013 Anupam Sengupta <anupamsg@gmail.com>
|
10
|
+
#
|
11
|
+
# All rights reserved.
|
12
|
+
#
|
13
|
+
# Redistribution and use in source and binary forms, with or without modification,
|
14
|
+
# are permitted provided that the following conditions are met:
|
15
|
+
#
|
16
|
+
# - Redistributions of source code must retain the above copyright notice, this
|
17
|
+
# list of conditions and the following disclaimer.
|
18
|
+
#
|
19
|
+
# - Redistributions in binary form must reproduce the above copyright notice, this
|
20
|
+
# list of conditions and the following disclaimer in the documentation and/or
|
21
|
+
# other materials provided with the distribution.
|
22
|
+
#
|
23
|
+
# - Neither the name of the organization nor the names of its contributors may
|
24
|
+
# be used to endorse or promote products derived from this software without
|
25
|
+
# specific prior written permission.
|
26
|
+
#
|
27
|
+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
28
|
+
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
29
|
+
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
30
|
+
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
31
|
+
# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
32
|
+
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
33
|
+
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
34
|
+
# ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
35
|
+
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
36
|
+
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
37
|
+
#
|
38
|
+
|
39
|
+
require 'structured_warnings'
|
40
|
+
|
41
|
+
module Tree::Utils
|
42
|
+
# Provides utility functions to measure various tree metrics.
|
43
|
+
module TreeMetricsHandler
|
44
|
+
def self.included(base)
|
45
|
+
|
46
|
+
# @!group Metrics and Measures
|
47
|
+
|
48
|
+
# @!attribute [r] size
|
49
|
+
# Total number of nodes in this (sub)tree, including this node.
|
50
|
+
#
|
51
|
+
# Size of the tree is defined as:
|
52
|
+
#
|
53
|
+
# Size:: Total number nodes in the subtree including this node.
|
54
|
+
#
|
55
|
+
# @return [Integer] Total number of nodes in this (sub)tree.
|
56
|
+
def size
|
57
|
+
inject(0) {|sum, node| sum + 1 if node}
|
58
|
+
end
|
59
|
+
|
60
|
+
# @!attribute [r] length
|
61
|
+
# Convenience synonym for {#size}.
|
62
|
+
#
|
63
|
+
# @deprecated This method name is ambiguous and may be removed. Use {#size} instead.
|
64
|
+
#
|
65
|
+
# @return [Integer] The total number of nodes in this (sub)tree.
|
66
|
+
# @see #size
|
67
|
+
def length
|
68
|
+
size()
|
69
|
+
end
|
70
|
+
|
71
|
+
# @!attribute [r] node_height
|
72
|
+
# Height of the (sub)tree from this node. Height of a node is defined as:
|
73
|
+
#
|
74
|
+
# Height:: Length of the longest downward path to a leaf from the node.
|
75
|
+
#
|
76
|
+
# - Height from a root node is height of the entire tree.
|
77
|
+
# - The height of a leaf node is zero.
|
78
|
+
#
|
79
|
+
# @return [Integer] Height of the node.
|
80
|
+
def node_height
|
81
|
+
return 0 if is_leaf?
|
82
|
+
1 + @children.collect { |child| child.node_height }.max
|
83
|
+
end
|
84
|
+
|
85
|
+
# @!attribute [r] node_depth
|
86
|
+
# Depth of this node in its tree. Depth of a node is defined as:
|
87
|
+
#
|
88
|
+
# Depth:: Length of the node's path to its root. Depth of a root node is zero.
|
89
|
+
#
|
90
|
+
# *Note* that the deprecated method {#depth} was incorrectly computing this value.
|
91
|
+
# Please replace all calls to the old method with {#node_depth} instead.
|
92
|
+
#
|
93
|
+
# {#level} is an alias for this method.
|
94
|
+
#
|
95
|
+
# @return [Integer] Depth of this node.
|
96
|
+
def node_depth
|
97
|
+
return 0 if is_root?
|
98
|
+
1 + parent.node_depth
|
99
|
+
end
|
100
|
+
|
101
|
+
# @!attribute [r] level
|
102
|
+
# Alias for {#node_depth}
|
103
|
+
#
|
104
|
+
# @see #node_depth
|
105
|
+
def level
|
106
|
+
node_depth
|
107
|
+
end
|
108
|
+
|
109
|
+
# @!attribute [r] depth
|
110
|
+
# Depth of the tree from this node. A single leaf node has a depth of 1.
|
111
|
+
#
|
112
|
+
# This method is *DEPRECATED* and may be removed in the subsequent releases.
|
113
|
+
# Note that the value returned by this method is actually the:
|
114
|
+
#
|
115
|
+
# _height_ + 1 of the node, *NOT* the _depth_.
|
116
|
+
#
|
117
|
+
# For correct and conventional behavior, please use {#node_depth} and
|
118
|
+
# {#node_height} methods instead.
|
119
|
+
#
|
120
|
+
# @return [Integer] depth of the node.
|
121
|
+
# @deprecated This method returns an incorrect value. Use the {#node_depth} method instead.
|
122
|
+
#
|
123
|
+
# @see #node_depth
|
124
|
+
def depth
|
125
|
+
warn DeprecatedMethodWarning, 'This method is deprecated. Please use node_depth() or node_height() instead (bug # 22535)'
|
126
|
+
|
127
|
+
return 1 if is_leaf?
|
128
|
+
1 + @children.collect { |child| child.depth }.max
|
129
|
+
end
|
130
|
+
|
131
|
+
# @!attribute [r] breadth
|
132
|
+
# Breadth of the tree at this node's level.
|
133
|
+
# A single node without siblings has a breadth of 1.
|
134
|
+
#
|
135
|
+
# Breadth is defined to be:
|
136
|
+
# Breadth:: Number of sibling nodes to this node + 1 (this node itself),
|
137
|
+
# i.e., the number of children the parent of this node has.
|
138
|
+
#
|
139
|
+
# @return [Integer] breadth of the node's level.
|
140
|
+
def breadth
|
141
|
+
is_root? ? 1 : parent.children.size
|
142
|
+
end
|
143
|
+
|
144
|
+
# @!attribute [r] in_degree
|
145
|
+
# The incoming edge-count of this node.
|
146
|
+
#
|
147
|
+
# In-degree is defined as:
|
148
|
+
# In-degree:: Number of edges arriving at the node (0 for root, 1 for all other nodes)
|
149
|
+
#
|
150
|
+
# - In-degree = 0 for a root or orphaned node
|
151
|
+
# - In-degree = 1 for a node which has a parent
|
152
|
+
#
|
153
|
+
# @return [Integer] The in-degree of this node.
|
154
|
+
def in_degree
|
155
|
+
is_root? ? 0 : 1
|
156
|
+
end
|
157
|
+
|
158
|
+
# @!attribute [r] out_degree
|
159
|
+
# The outgoing edge-count of this node.
|
160
|
+
#
|
161
|
+
# Out-degree is defined as:
|
162
|
+
# Out-degree:: Number of edges leaving the node (zero for leafs)
|
163
|
+
#
|
164
|
+
# @return [Integer] The out-degree of this node.
|
165
|
+
def out_degree
|
166
|
+
is_leaf? ? 0 : children.size
|
167
|
+
end
|
168
|
+
|
169
|
+
# @!endgroup
|
170
|
+
end # self.included
|
171
|
+
end
|
172
|
+
end
|