rubytree 0.8.3 → 0.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +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
|