8
8
use Fhaculty \Graph \Vertex ;
9
9
10
10
/**
11
+ * Abstract algorithm base class for working with directed, rooted trees
11
12
*
13
+ * Directed trees have an designated root Vertex, which is the uppermost Vertex.
14
+ * Every other Vertex is either a directed child of this root Vertex or an
15
+ * indirect descendant (recursive child).
16
+ *
17
+ * There are two common implementations of directed trees:
18
+ *
19
+ * - Usual OutTree implementation where Edges "point away" from root Vertex
20
+ *
21
+ * ROOT
22
+ * / \
23
+ * A <--/ \--> B
24
+ * \
25
+ * \--> C
26
+ *
27
+ * - Alternative InTree implementation where Edges "point towards" root Vertex
28
+ *
29
+ * ROOT
30
+ * ^ ^
31
+ * / \
32
+ * A B
33
+ * ^
34
+ * \
35
+ * C
36
+ *
37
+ * It's your choice on how to direct the edges, but make sure they all point in
38
+ * the "same direction", or it will not be a valid tree anymore. However your
39
+ * decision may be, in the above example, ROOT is always the root Vertex,
40
+ * B is the parent of "C" and A, B are the children of ROOT.
41
+ *
42
+ * For performance reasons, except for `isTree()`, none of the below methods
43
+ * check if the given Graph is actually a valid tree. So make sure to verify
44
+ * `isTree()` returns `true` before relying on any of the methods.
45
+ *
46
+ * @link http://en.wikipedia.org/wiki/Arborescence_%28graph_theory%29
12
47
* @link http://en.wikipedia.org/wiki/Spaghetti_stack
13
- * @see OutTree
48
+ * @see OutTree usual implementation where Edges "point away" from root vertex
49
+ * @see InTree alternative implementation where Edges "point towards" root vertex
14
50
*/
15
51
abstract class BaseDirected extends Tree
16
52
{
@@ -19,6 +55,8 @@ abstract class BaseDirected extends Tree
19
55
*
20
56
* @return Vertex
21
57
* @throws UnderflowException if given graph is empty or no possible root candidate was found (check isTree()!)
58
+ * @uses Graph::getVertices() to iterate over each Vertex
59
+ * @uses self::isVertexPossibleRoot() to check if any Vertex is a possible root candidate
22
60
*/
23
61
public function getVertexRoot ()
24
62
{
@@ -34,8 +72,9 @@ public function getVertexRoot()
34
72
* checks if this is a tree
35
73
*
36
74
* @return boolean
37
- * @uses Graph::isEmpty()
38
- * @uses self::getVertexRoot() to actually check tree
75
+ * @uses Graph::isEmpty() to skip empty Graphs (an empty is Graph is a valid tree)
76
+ * @uses self::getVertexRoot() to get root Vertex to start search from
77
+ * @uses self::getVerticesSubtree() to count number of vertices connected to root
39
78
*/
40
79
public function isTree ()
41
80
{
@@ -60,6 +99,7 @@ public function isTree()
60
99
return false ;
61
100
}
62
101
102
+ // check number of vertices reachable from root should match total number of vertices
63
103
return ($ num === $ this ->graph ->getNumberOfVertices ());
64
104
}
65
105
@@ -70,6 +110,7 @@ public function isTree()
70
110
* @throws UnderflowException if vertex has no parent (is a root vertex)
71
111
* @throws UnexpectedValueException if vertex has more than one possible parent (check isTree()!)
72
112
* @return Vertex
113
+ * @uses self::getVerticesParents() to get array of parent vertices
73
114
*/
74
115
public function getVertexParent (Vertex $ vertex )
75
116
{
@@ -93,8 +134,24 @@ public function getVertexParent(Vertex $vertex)
93
134
*/
94
135
abstract public function getVerticesChildren (Vertex $ vertex );
95
136
137
+ /**
138
+ * internal helper to get all parents vertices
139
+ *
140
+ * a valid tree vertex only ever has a single parent, expect for the root,
141
+ * which has none.
142
+ *
143
+ * @param Vertex $vertex
144
+ * @return Vertex[]
145
+ */
96
146
abstract protected function getVerticesParent (Vertex $ vertex );
97
147
148
+ /**
149
+ * check if given vertex is a possible root (i.e. has no parent)
150
+ *
151
+ * @param Vertex $vertex
152
+ * @return boolean
153
+ * @uses self::getVerticesParent()
154
+ */
98
155
protected function isVertexPossibleRoot (Vertex $ vertex )
99
156
{
100
157
return (count ($ this ->getVerticesParent ($ vertex )) === 0 );
@@ -105,13 +162,22 @@ protected function isVertexPossibleRoot(Vertex $vertex)
105
162
*
106
163
* @param Vertex $vertex
107
164
* @return boolean
108
- * @uses self::getVerticesChildren()
165
+ * @uses self::getVerticesChildren() to check given vertex has no children
109
166
*/
110
167
public function isVertexLeaf (Vertex $ vertex )
111
168
{
112
169
return (count ($ this ->getVerticesChildren ($ vertex )) === 0 );
113
170
}
114
171
172
+ /**
173
+ * checks if the given $vertex is an internal vertex (has children and is not root)
174
+ *
175
+ * @param Vertex $vertex
176
+ * @return boolean
177
+ * @uses self::getVerticesParent() to check given vertex has a parent (is not root)
178
+ * @uses self::getVerticesChildren() to check given vertex has children (is not a leaf)
179
+ * @see \Fhaculty\Graph\Algorithm\Tree\Base::isVertexInternal() for more information
180
+ */
115
181
public function isVertexInternal (Vertex $ vertex )
116
182
{
117
183
return ($ this ->getVerticesParent ($ vertex ) && $ this ->getVerticesChildren ($ vertex ));
0 commit comments