1 /*
2 * Created on Mar 3, 2007
3 *
4 * Copyright (c) 2007, The JUNG Authors
5 *
6 * All rights reserved.
7 *
8 * This software is open-source under the BSD license; see either
9 * "license.txt" or
10 * https://github.com/jrtom/jung/blob/master/LICENSE for a description.
11 */
12 package edu.uci.ics.jung.graph.util;
13
14 import edu.uci.ics.jung.graph.Forest;
15 import edu.uci.ics.jung.graph.Tree;
16
17 import java.util.ArrayList;
18 import java.util.Collection;
19 import java.util.List;
20
21 /**
22 * Contains static methods for operating on instances of <code>Tree</code>.
23 */
24 public class TreeUtils
25 {
26 /**
27 * @param <V> the vertex type
28 * @param <E> the edge type
29 * @param forest the forest whose roots are to be returned
30 * @return the roots of this forest.
31 */
32 public static <V,E> List<V> getRoots(Forest<V,E> forest)
33 {
34 List<V> roots = new ArrayList<V>();
35 for(Tree<V,E> tree : forest.getTrees()) {
36 roots.add(tree.getRoot());
37 }
38 return roots;
39 }
40
41 /**
42 * Returns the subtree of <code>tree</code> which is rooted at <code>root</code> as a <code>Forest</code>.
43 * The tree returned is an independent entity, although it uses the same vertex and edge objects.
44 * @param <V> the vertex type
45 * @param <E> the edge type
46 * @param forest the tree whose subtree is to be extracted
47 * @param root the root of the subtree to be extracted
48 * @return the subtree of <code>tree</code> which is rooted at <code>root</code>
49 * @throws InstantiationException if a new tree of the same type cannot be created
50 * @throws IllegalAccessException if a new tree of the same type cannot be created
51 */
52 @SuppressWarnings("unchecked")
53 public static <V,E> Tree<V,E> getSubTree(Forest<V,E> forest, V root) throws InstantiationException, IllegalAccessException
54 {
55 if (!forest.containsVertex(root))
56 throw new IllegalArgumentException("Specified tree does not contain the specified root as a vertex");
57 Forest<V,E> subforest = forest.getClass().newInstance();
58 subforest.addVertex(root);
59 growSubTree(forest, subforest, root);
60
61 return subforest.getTrees().iterator().next();
62 }
63
64 /**
65 * Populates <code>subtree</code> with the subtree of <code>tree</code>
66 * which is rooted at <code>root</code>.
67 * @param <V> the vertex type
68 * @param <E> the edge type
69 * @param tree the tree whose subtree is to be extracted
70 * @param subTree the tree instance which is to be populated with the subtree of <code>tree</code>
71 * @param root the root of the subtree to be extracted
72 */
73 public static <V,E> void growSubTree(Forest<V,E> tree, Forest<V,E> subTree, V root) {
74 if(tree.getSuccessorCount(root) > 0) {
75 Collection<E> edges = tree.getOutEdges(root);
76 for(E e : edges) {
77 subTree.addEdge(e, tree.getEndpoints(e));
78 }
79 Collection<V> kids = tree.getSuccessors(root);
80 for(V kid : kids) {
81 growSubTree(tree, subTree, kid);
82 }
83 }
84 }
85
86 /**
87 * Connects <code>subTree</code> to <code>tree</code> by attaching it as a child
88 * of <code>node</code> with edge <code>connectingEdge</code>.
89 * @param <V> the vertex type
90 * @param <E> the edge type
91 * @param tree the tree to which <code>subTree</code> is to be added
92 * @param subTree the tree which is to be grafted on to <code>tree</code>
93 * @param node the parent of <code>subTree</code> in its new position in <code>tree</code>
94 * @param connectingEdge the edge used to connect <code>subtree</code>'s root as a child of <code>node</code>
95 */
96 public static <V,E> void addSubTree(Forest<V,E> tree, Forest<V,E> subTree,
97 V node, E connectingEdge) {
98 if (node != null && !tree.containsVertex(node))
99 throw new IllegalArgumentException("Specified tree does not contain the specified node as a vertex");
100 V root = subTree.getTrees().iterator().next().getRoot();
101 addFromSubTree(tree, subTree, connectingEdge, node, root);
102 }
103
104 public static <V,E> void addFromSubTree(Forest<V,E> tree, Forest<V,E> subTree,
105 E edge, V parent, V root) {
106
107 // add edge connecting parent and root to tree
108 if(edge != null && parent != null) {
109 tree.addEdge(edge, parent, root);
110 } else {
111 tree.addVertex(root);
112 }
113
114 Collection<E> outEdges = subTree.getOutEdges(root);
115 for(E e : outEdges) {
116 V opposite = subTree.getOpposite(root, e);
117 addFromSubTree(tree, subTree, e, root, opposite);
118 }
119 }
120 }