View Javadoc
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 }