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

org.jgrapht.traverse.TopologicalOrderIterator Maven / Gradle / Ivy

Go to download

JGraphT is a free Java graph library that provides mathematical graph-theory objects and algorithms

The newest version!
/* ==========================================
 * JGraphT : a free Java graph-theory library
 * ==========================================
 *
 * Project Info:  http://jgrapht.sourceforge.net/
 * Project Creator:  Barak Naveh (http://sourceforge.net/users/barak_naveh)
 *
 * (C) Copyright 2003-2007, by Barak Naveh and Contributors.
 *
 * This library is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation; either version 2.1 of the License, or
 * (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
 * License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this library; if not, write to the Free Software Foundation,
 * Inc.,
 * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
 */
/* -----------------------------
 * TopologicalOrderIterator.java
 * -----------------------------
 * (C) Copyright 2004-2007, by Marden Neubert and Contributors.
 *
 * Original Author:  Marden Neubert
 * Contributor(s):   Barak Naveh, John V. Sichi
 *
 * $Id: TopologicalOrderIterator.java 584 2008-01-26 08:54:05Z perfecthash $
 *
 * Changes
 * -------
 * 17-Dec-2004 : Initial revision (MN);
 * 25-Apr-2005 : Fixes for start vertex order (JVS);
 * 06-Jun-2005 : Made generic (CH);
 *
 */
package org.jgrapht.traverse;

import java.util.*;

import org.jgrapht.*;
import org.jgrapht.util.*;


/**
 * Implements topological order traversal for a directed acyclic graph. A
 * topological sort is a permutation p of the vertices of a graph such
 * that an edge (i,j) implies that i appears before j
 * in p (Skiena 1990, p. 208). See also 
 * http://mathworld.wolfram.com/TopologicalSort.html.
 *
 * 

See "Algorithms in Java, Third Edition, Part 5: Graph Algorithms" by * Robert Sedgewick and "Data Structures and Algorithms with Object-Oriented * Design Patterns in Java" by Bruno R. Preiss for implementation alternatives. * The latter can be found online at * http://www.brpreiss.com/books/opus5/

* *

For this iterator to work correctly the graph must be acyclic, and must * not be modified during iteration. Currently there are no means to ensure * that, nor to fail-fast; the results with cyclic input (including self-loops) * or concurrent modifications are undefined. To precheck a graph for cycles, * consider using {@link org.jgrapht.alg.CycleDetector} or {@link * org.jgrapht.alg.StrongConnectivityInspector}.

* * @author Marden Neubert * @since Dec 18, 2004 */ public class TopologicalOrderIterator extends CrossComponentIterator { //~ Instance fields -------------------------------------------------------- private Queue queue; private Map inDegreeMap; //~ Constructors ----------------------------------------------------------- /** * Creates a new topological order iterator over the directed graph * specified, with arbitrary tie-breaking in case of partial order. * Traversal will start at one of the graph's sources. See the * definition of source at * http://mathworld.wolfram.com/Source.html. * * @param dg the directed graph to be iterated. */ public TopologicalOrderIterator(DirectedGraph dg) { this(dg, new LinkedListQueue()); } /** * Creates a new topological order iterator over the directed graph * specified, with a user-supplied queue implementation to allow customized * control over tie-breaking in case of partial order. Traversal will start * at one of the graph's sources. See the definition of source at * http://mathworld.wolfram.com/Source.html. * * @param dg the directed graph to be iterated. * @param queue queue to use for tie-break in case of partial order (e.g. a * PriorityQueue can be used to break ties according to vertex priority); * must be initially empty */ public TopologicalOrderIterator(DirectedGraph dg, Queue queue) { this(dg, queue, new HashMap()); } // NOTE: This is a hack to deal with the fact that CrossComponentIterator // needs to know the start vertex in its constructor private TopologicalOrderIterator( DirectedGraph dg, Queue queue, Map inDegreeMap) { this(dg, initialize(dg, queue, inDegreeMap)); this.queue = queue; this.inDegreeMap = inDegreeMap; // empty queue would indicate presence of cycles (no roots found) assert (!queue.isEmpty()); } // NOTE: This is intentionally private, because starting the sort "in the // middle" doesn't make sense. private TopologicalOrderIterator(DirectedGraph dg, V start) { super(dg, start); } //~ Methods ---------------------------------------------------------------- /** * @see CrossComponentIterator#isConnectedComponentExhausted() */ protected boolean isConnectedComponentExhausted() { // FIXME jvs 25-Apr-2005: This isn't correct for a graph with more than // one component. We will actually exhaust a connected component // before the queue is empty, because initialize adds roots from all // components to the queue. return queue.isEmpty(); } /** * @see CrossComponentIterator#encounterVertex(Object, Object) */ protected void encounterVertex(V vertex, E edge) { putSeenData(vertex, null); decrementInDegree(vertex); } /** * @see CrossComponentIterator#encounterVertexAgain(Object, Object) */ protected void encounterVertexAgain(V vertex, E edge) { decrementInDegree(vertex); } /** * @see CrossComponentIterator#provideNextVertex() */ protected V provideNextVertex() { return queue.remove(); } /** * Decrements the in-degree of a vertex. * * @param vertex the vertex whose in-degree will be decremented. */ private void decrementInDegree(V vertex) { ModifiableInteger inDegree = inDegreeMap.get(vertex); if (inDegree.value > 0) { inDegree.value--; if (inDegree.value == 0) { queue.offer(vertex); } } } /** * Initializes the internal traversal object structure. Sets up the internal * queue with the directed graph vertices and creates the control structure * for the in-degrees. * * @param dg the directed graph to be iterated. * @param queue initializer for queue * @param inDegreeMap initializer for inDegreeMap * * @return start vertex */ private static V initialize( DirectedGraph dg, Queue queue, Map inDegreeMap) { for (Iterator i = dg.vertexSet().iterator(); i.hasNext();) { V vertex = i.next(); int inDegree = dg.inDegreeOf(vertex); inDegreeMap.put(vertex, new ModifiableInteger(inDegree)); if (inDegree == 0) { queue.offer(vertex); } } if (queue.isEmpty()) { return null; } else { return queue.peek(); } } //~ Inner Classes ---------------------------------------------------------- // NOTE jvs 22-Dec-2006: For JDK1.4-compatibility, we can't assume // that LinkedList implements Queue, since that wasn't introduced // until JDK1.5, so use an adapter here. Move this to // top-level in org.jgrapht.util if anyone else needs it. private static class LinkedListQueue extends LinkedList implements Queue { private static final long serialVersionUID = 4217659843476891334L; public T element() { return getFirst(); } public boolean offer(T o) { return add(o); } public T peek() { if (isEmpty()) { return null; } return getFirst(); } public T poll() { if (isEmpty()) { return null; } return removeFirst(); } public T remove() { return removeFirst(); } } } // End TopologicalOrderIterator.java




© 2015 - 2024 Weber Informatics LLC | Privacy Policy