All Downloads are FREE. Search and download functionalities are using the official Maven repository.

edu.uci.ics.jung.graph.DelegateForest Maven / Gradle / Ivy

There is a newer version: 2.1.1
Show newest version
package edu.uci.ics.jung.graph;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;

import edu.uci.ics.jung.graph.util.EdgeType;
import edu.uci.ics.jung.graph.util.Pair;
import edu.uci.ics.jung.graph.util.TreeUtils;

/**
 * An implementation of Forest that delegates to a specified DirectedGraph
 * instance.
 * @author Tom Nelson
 *
 * @param  the vertex type
 * @param  the edge type
 */
@SuppressWarnings("serial")
public class DelegateForest extends GraphDecorator implements Forest 
{
	/**
	 * Creates an instance backed by a new {@code DirectedSparseGraph} instance.
	 */
	public DelegateForest() {
		this(new DirectedSparseGraph());
	}

	/**
	 * Creates an instance backed by the input {@code DirectedGraph}.
	 * @param delegate the graph to which operations will be delegated
	 */
	public DelegateForest(DirectedGraph delegate) {
		super(delegate);
	}

	/**
	 * Add an edge to the tree, connecting v1, the parent and v2, the child.
	 * v1 must already exist in the tree, and v2 must not already exist
	 * the passed edge must be unique in the tree. Passing an edgeType
	 * other than EdgeType.DIRECTED may cause an illegal argument exception
	 * in the delegate graph.
	 *
	 * @param e a unique edge to add
	 * @param v1 the parent node
	 * @param v2 the child node
	 * @param edgeType should be EdgeType.DIRECTED
	 * @return true if this call mutates the underlying graph
	 * @see edu.uci.ics.jung.graph.Graph#addEdge(java.lang.Object, java.lang.Object, java.lang.Object, edu.uci.ics.jung.graph.util.EdgeType)
	 */
	@Override
	public boolean addEdge(E e, V v1, V v2, EdgeType edgeType) {
		if(delegate.getVertices().contains(v1) == false) {
			throw new IllegalArgumentException("Tree must already contain "+v1);
		}
		if(delegate.getVertices().contains(v2)) {
			throw new IllegalArgumentException("Tree must not already contain "+v2);
		}
		return delegate.addEdge(e, v1, v2, edgeType);
	}

	/**
	 * Add vertex as a root of the tree
	 *
	 * @param vertex the tree root to add
	 * @return true if this call mutates the underlying graph
	 * @see edu.uci.ics.jung.graph.Graph#addVertex(java.lang.Object)
	 */
	@Override
	public boolean addVertex(V vertex) {
		setRoot(vertex);
		return true;
	}

	/**
	 * Removes edge from this tree, and the subtree rooted
	 * at the child vertex incident to edge.
	 * (The subtree is removed to ensure that the tree in which the edge
	 * was found is still a tree rather than a forest.  To change this
	 * behavior so that the
	 * @param edge the edge to remove
	 * @return true iff the tree was modified
	 * @see edu.uci.ics.jung.graph.Hypergraph#removeEdge(java.lang.Object)
	 */
	@Override
	public boolean removeEdge(E edge) {
	    return removeEdge(edge, true);
	}

	/**
	 * Removes edge from this tree.
	 * If remove_subtree is true, removes
	 * the subtree rooted at the child vertex incident to edge.
	 * Otherwise, leaves the subtree intact as a new component tree of this
	 * forest.
	 * @param edge the edge to remove
	 * @param remove_subtree if true, remove the subtree
	 * @return true iff the tree was modified
	 */
	public boolean removeEdge(E edge, boolean remove_subtree)
	{
        if (!delegate.containsEdge(edge))
            return false;
        V child = getDest(edge);
        if (remove_subtree)
            return removeVertex(child);
        else
        {
            delegate.removeEdge(edge);
            return false;
        }
	}

	/**
	 * Removes vertex from this tree, and the subtree
	 * rooted at vertex.
	 * @param vertex the vertex to remove
	 * @return true iff the tree was modified
	 * @see edu.uci.ics.jung.graph.Hypergraph#removeVertex(java.lang.Object)
	 */
	@Override
	public boolean removeVertex(V vertex) {
	    return removeVertex(vertex, true);
	}

	/**
	 * Removes vertex from this tree.
     * If remove_subtrees is true, removes
     * the subtrees rooted at the children of vertex.
     * Otherwise, leaves these subtrees intact as new component trees of this
     * forest.
     * @param vertex the vertex to remove
	 * @param remove_subtrees if true, remove the subtrees
	 * rooted at vertex's children
	 * @return true iff the tree was modified
	 */
	public boolean removeVertex(V vertex, boolean remove_subtrees)
	{
        if (!delegate.containsVertex(vertex))
            return false;
        if (remove_subtrees)
            for(V v : new ArrayList(delegate.getSuccessors(vertex)))
                removeVertex(v, true);
        return delegate.removeVertex(vertex);
	}

	/**
	 * returns an ordered list of the nodes beginning at the root
	 * and ending at the passed child node, including all intermediate
	 * nodes.
	 * @param child the last node in the path from the root
	 * @return an ordered list of the nodes from root to child
	 */
	public List getPath(V child) {
        if (!delegate.containsVertex(child))
            return null;
		List list = new ArrayList();
		list.add(child);
		V parent = getParent(child);
		while(parent != null) {
			list.add(list.size(), parent);
			parent = getParent(parent);
		}
		return list;
	}

	public V getParent(V child) {
        if (!delegate.containsVertex(child))
            return null;
		Collection parents = delegate.getPredecessors(child);
		if(parents.size() > 0) {
			return parents.iterator().next();
		}
		return null;
	}

	/**
	 * @return the root of the tree, or null if the tree has > 1 roots
	 */
	public V getRoot() {
		V root = null;
		for (V v : delegate.getVertices()) {
			if (delegate.getPredecessorCount(v) == 0) {
				if (root == null) {
					root = v;
				} else {
					// we've found > 1 root, return null
					return null;
				}
			}
		}
		return root;
	}

	/**
	 * adds root as a root of the tree
	 * @param root the initial tree root
	 */
	public void setRoot(V root) {
		delegate.addVertex(root);
	}

	/**
	 * removes a node from the tree, causing all descendants of
	 * the removed node also to be removed
	 * @param orphan the node to remove
	 * @return whether this call mutates the underlying graph
	 */
	public boolean removeChild(V orphan) {
		return removeVertex(orphan);
	}

	/**
	 * computes and returns the depth of the tree from the
	 * root to the passed vertex
	 *
	 * @param v the node who's depth is computed
	 * @return the depth to the passed node.
	 */
	public int getDepth(V v) {
		return getPath(v).size();
	}

	/**
	 * computes and returns the height of the tree
	 *
	 * @return the height
	 */
	public int getHeight() {
		int height = 0;
		for(V v : getVertices()) {
			height = Math.max(height, getDepth(v));
		}
		return height;
	}

	/**
	 * @param v the vertex to test
	 * @return true if v is neither a leaf
	 * nor a root
	 */
	public boolean isInternal(V v) {
		return isLeaf(v) == false && isRoot(v) == false;
	}

	/**
	 * @param v the vertex to test
	 * @return {@code true} if {@code v} has no child nodes.
	 */
	public boolean isLeaf(V v) {
		return getChildren(v).size() == 0;
	}

	/**
	 * @param v the vertex whose children are to be returned
	 * @return the children of {@code v}.
	 */
	public Collection getChildren(V v) {
		return delegate.getSuccessors(v);
	}

	/**
	 * @param v the vertex to test
	 * @return {@code true} if {@code v} has no parent node.
	 */
	public boolean isRoot(V v) {
		return getParent(v) == null;
	}

	@Override
    public int getIncidentCount(E edge)
    {
        return 2;
    }

	@SuppressWarnings("unchecked")
	@Override
	public boolean addEdge(E edge, Collection vertices) {
		Pair pair = null;
		if(vertices instanceof Pair) {
			pair = (Pair)vertices;
		} else {
			pair = new Pair(vertices);
		}
		return addEdge(edge, pair.getFirst(), pair.getSecond());
	}

	/**
	 * @return the root of each tree of this forest as a {@code Collection}.
	 */
	public Collection getRoots() {
		Collection roots = new HashSet();
		for(V v : delegate.getVertices()) {
			if(delegate.getPredecessorCount(v) == 0) {
				roots.add(v);
			}
		}
		return roots;
	}

	public Collection> getTrees() {
		Collection> trees = new HashSet>();
		for(V v : getRoots()) {
			Tree tree = new DelegateTree();
			tree.addVertex(v);
			TreeUtils.growSubTree(this, tree, v);
			trees.add(tree);
		}
		return trees;
	}

	/**
	 * Adds {@code tree} to this graph as an element of this forest.
	 *
	 * @param tree the tree to add to this forest as a component
	 */
	public void addTree(Tree tree) {
		TreeUtils.addSubTree(this, tree, null, null);
	}

    public int getChildCount(V vertex)
    {
        return delegate.getSuccessorCount(vertex);
    }

    public Collection getChildEdges(V vertex)
    {
        return delegate.getOutEdges(vertex);
    }

    public E getParentEdge(V vertex)
    {
        if (isRoot(vertex))
            return null;
        return delegate.getInEdges(vertex).iterator().next();
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy