Skip to content
Browse files

Replaced the old breadth-first and depth-first iterators

  • Loading branch information...
1 parent a22a034 commit 70ec71e24e8452f3fa50c3b39d92df90ee8ec238 @sbalev sbalev committed Sep 2, 2011
View
255 src/org/graphstream/graph/BreadthFirstIterator.java
@@ -1,230 +1,75 @@
-/*
- * Copyright 2006 - 2011
- * Julien Baudry <julien.baudry@graphstream-project.org>
- * Antoine Dutot <antoine.dutot@graphstream-project.org>
- * Yoann Pigné <yoann.pigne@graphstream-project.org>
- * Guilhelm Savin <guilhelm.savin@graphstream-project.org>
- *
- * This file is part of GraphStream <http://graphstream-project.org>.
- *
- * GraphStream is a library whose purpose is to handle static or dynamic
- * graph, create them from scratch, file or any source and display them.
- *
- * This program is free software distributed under the terms of two licenses, the
- * CeCILL-C license that fits European law, and the GNU Lesser General Public
- * License. You can use, modify and/ or redistribute the software under the terms
- * of the CeCILL-C license as circulated by CEA, CNRS and INRIA at the following
- * URL <http://www.cecill.info> or under the terms of the GNU LGPL as published by
- * the Free Software Foundation, either version 3 of the License, or (at your
- * option) any later version.
- *
- * This program 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 program. If not, see <http://www.gnu.org/licenses/>.
- *
- * The fact that you are presently reading this means that you have had
- * knowledge of the CeCILL-C and LGPL licenses and that you accept their terms.
- */
package org.graphstream.graph;
-import java.util.HashMap;
import java.util.Iterator;
-import java.util.LinkedList;
import java.util.NoSuchElementException;
-import org.graphstream.graph.Edge;
-import org.graphstream.graph.Node;
-
-/**
- * Iterator allowing to explore a graph in a breadth-first way.
- *
- * This iterator also allows to compute the depth or each node (number of edges
- * crossed to reach a node from the starting node) as well as the maximum
- * depth. Be careful that this depth does not take eventual weights of edges,
- * it only counts edges. The depth of each node and the depth max are known
- * only when all the nodes have been processed by this iterator (only when
- * {@link #hasNext()} returns false).
- *
- * @complexity O(n+m) with n the number of nodes and m the number of edges.
- * @since 20040730
- */
public class BreadthFirstIterator<T extends Node> implements Iterator<T> {
- // Attributes
-
- /**
- * Respect the edge orientation?.
- */
- protected boolean directed = true;
-
- /**
- * Already processed nodes.
- */
- protected HashMap<T,Integer> closed = new HashMap<T,Integer>();
-
- /**
- * Nodes remaining to process. The iteration continues as long as this array
- * is not empty.
- */
- protected LinkedList<T> open = new LinkedList<T>();
-
- /**
- * Maximum depth.
- */
- protected int depthMax = 0;
-
- // Constructors
-
- /**
- * New breadth-first iterator starting at the given start node.
- *
- * @param startNode
- * The node where the graph exploration begins.
- */
- public BreadthFirstIterator(Node startNode) {
- this(startNode, true);
- }
+ protected boolean directed;
+ protected Graph graph;
+ protected Node[] queue;
+ protected int[] depth;
+ protected int qHead, qTail;
- /**
- * New breadth-first iterator starting at the given start node.
- *
- * @param startNode
- * The node where the graph exploration begins.
- * @param directed
- * If true the iterator respects the edge direction (the
- * default).
- */
- @SuppressWarnings("unchecked")
public BreadthFirstIterator(Node startNode, boolean directed) {
- open.add((T)startNode);
- closed.put((T)startNode,0);
this.directed = directed;
+ graph = startNode.getGraph();
+ int n = graph.getNodeCount();
+ queue = new Node[n];
+ depth = new int[n];
+
+ int s = startNode.getIndex();
+ for (int i = 0; i < n; i++)
+ depth[i] = i == s ? 0 : -1;
+ queue[0] = startNode;
+ qHead = 0;
+ qTail = 1;
}
- // Accessors
-
- /**
- * Is this iterator respecting edge orientation ?.
- *
- * @return True if edge orientation is respected (the default).
- */
- public boolean isDirected() {
- return directed;
- }
-
- /**
- * Depth of the more distant node from the starting point of the BFS, this is also known as
- * the eccentricity if the graph non-weighted. This method can only be used reliably after all
- * the nodes have been processed.
- *
- * @return The maximum depth of a node from the starting node (in edge jumps).
- */
- public int getDepthMax() {
- return depthMax;
- }
-
- /**
- * Depth of a given node. The depth here is minimal number of edges to cross to reach
- * the given node from the starting node of the BFS. Weights are not used.
- * This method can only be used reliably after all the nodes
- * have been processed, if the depth has not been computed -1 is returned.
- *
- * @param node
- * The node for which the depth is required.
- * @return The depth of the given node.
- */
- public int getDepthOf(Node node) {
- Integer i = closed.get(node);
-
- if(i != null)
- return (int)i;
-
- return -1;
- }
-
- /**
- * Is the given node tabu?.
- *
- * Tabu nodes are nodes that have already been discovered (and are therefore either
- * in closed or open or both).
- *
- * @param node
- * The node to test.
- * @return True if tabu.
- */
- protected boolean tabu(T node) {
- return closed.containsKey(node);
+ public BreadthFirstIterator(Node startNode) {
+ this(startNode, true);
}
- /**
- * Is there a next node to process?.
- *
- * @return True if it remains nodes.
- */
public boolean hasNext() {
- return open.size() > 0;
+ return qHead < qTail;
}
- /**
- * Next node to process, in BF order.
- *
- * @return The next node.
- */
- public T next() throws NoSuchElementException {
- if (open.size() > 0) {
- T next = open.removeFirst();
-
- addNeighborsOf(next);
-
- return next;
- } else {
- throw new NoSuchElementException("no more elements in iterator");
+ @SuppressWarnings("unchecked")
+ public T next() {
+ if (qHead >= qTail)
+ throw new NoSuchElementException();
+ Node current = queue[qHead++];
+ int level = depth[current.getIndex()] + 1;
+ Iterable<Edge> edges = directed ? current.getEachLeavingEdge()
+ : current.getEachEdge();
+ for (Edge e : edges) {
+ Node node = e.getOpposite(current);
+ int j = node.getIndex();
+ if (depth[j] == -1) {
+ queue[qTail++] = node;
+ depth[j] = level;
+ }
}
+ return (T)current;
}
- /**
- * Append the neighbors of the given node (excepted nodes already processed/marked)
- * in the list of nodes to process next.
- *
- * @param node
- * The nodes the neighbors are to be processed.
- */
- protected void addNeighborsOf(T node) {
- Iterator<? extends Edge> k;
-
- if (directed)
- k = node.getLeavingEdgeIterator();
- else
- k = node.getEdgeIterator();
+ public void remove() {
+ throw new UnsupportedOperationException(
+ "This iterator does not support remove");
+ }
- boolean found = false;
- int curDepth = ((int)closed.get(node)) + 1;
-
- while (k.hasNext()) {
- Edge edge = k.next();
- T adj = edge.getOpposite(node);
+ public int getDepthOf(Node node) {
+ return depth[node.getIndex()];
+ }
- if (!tabu(adj)) {
- open.add(adj);
- closed.put(adj, curDepth);
- found = true;
- }
- }
-
- if(found && curDepth > depthMax)
- depthMax = curDepth;
+ public int getDepthMax() {
+ return depth[queue[qTail - 1].getIndex()];
}
- // Commands
+ public boolean tabu(Node node) {
+ return depth[node.getIndex()] != -1;
+ }
- /**
- * Unsupported with this iterator.
- */
- public void remove() throws UnsupportedOperationException,
- IllegalStateException {
- throw new UnsupportedOperationException(
- "cannot remove a node using this iterator (yet)");
+ public boolean isDirected() {
+ return directed;
}
-}
+}
View
75 src/org/graphstream/graph/BreadthFirstIteratorIndexed.java
@@ -1,75 +0,0 @@
-package org.graphstream.graph;
-
-import java.util.Iterator;
-import java.util.NoSuchElementException;
-
-public class BreadthFirstIteratorIndexed<T extends Node> implements Iterator<T> {
- protected boolean directed;
- protected Graph graph;
- protected Node[] queue;
- protected int[] depth;
- protected int qHead, qTail;
-
- public BreadthFirstIteratorIndexed(Node startNode, boolean directed) {
- this.directed = directed;
- graph = startNode.getGraph();
- int n = graph.getNodeCount();
- queue = new Node[n];
- depth = new int[n];
-
- int s = startNode.getIndex();
- for (int i = 0; i < n; i++)
- depth[i] = i == s ? 0 : -1;
- queue[0] = startNode;
- qHead = 0;
- qTail = 1;
- }
-
- public BreadthFirstIteratorIndexed(Node startNode) {
- this(startNode, true);
- }
-
- public boolean hasNext() {
- return qHead < qTail;
- }
-
- @SuppressWarnings("unchecked")
- public T next() {
- if (qHead >= qTail)
- throw new NoSuchElementException();
- Node current = queue[qHead++];
- int level = depth[current.getIndex()] + 1;
- Iterable<Edge> edges = directed ? current.getEachLeavingEdge()
- : current.getEachEdge();
- for (Edge e : edges) {
- Node node = e.getOpposite(current);
- int j = node.getIndex();
- if (depth[j] == -1) {
- queue[qTail++] = node;
- depth[j] = level;
- }
- }
- return (T)current;
- }
-
- public void remove() {
- throw new UnsupportedOperationException(
- "This iterator does not support remove");
- }
-
- public int getDepthOf(Node node) {
- return depth[node.getIndex()];
- }
-
- public int getMaxDepth() {
- return depth[queue[qTail - 1].getIndex()];
- }
-
- public boolean isTabu(Node node) {
- return depth[node.getIndex()] != -1;
- }
-
- public boolean isDirected() {
- return directed;
- }
-}
View
213 src/org/graphstream/graph/DepthFirstIterator.java
@@ -1,178 +1,91 @@
-/*
- * Copyright 2006 - 2011
- * Julien Baudry <julien.baudry@graphstream-project.org>
- * Antoine Dutot <antoine.dutot@graphstream-project.org>
- * Yoann Pigné <yoann.pigne@graphstream-project.org>
- * Guilhelm Savin <guilhelm.savin@graphstream-project.org>
- *
- * This file is part of GraphStream <http://graphstream-project.org>.
- *
- * GraphStream is a library whose purpose is to handle static or dynamic
- * graph, create them from scratch, file or any source and display them.
- *
- * This program is free software distributed under the terms of two licenses, the
- * CeCILL-C license that fits European law, and the GNU Lesser General Public
- * License. You can use, modify and/ or redistribute the software under the terms
- * of the CeCILL-C license as circulated by CEA, CNRS and INRIA at the following
- * URL <http://www.cecill.info> or under the terms of the GNU LGPL as published by
- * the Free Software Foundation, either version 3 of the License, or (at your
- * option) any later version.
- *
- * This program 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 program. If not, see <http://www.gnu.org/licenses/>.
- *
- * The fact that you are presently reading this means that you have had
- * knowledge of the CeCILL-C and LGPL licenses and that you accept their terms.
- */
package org.graphstream.graph;
-import java.util.HashSet;
import java.util.Iterator;
-import java.util.LinkedList;
import java.util.NoSuchElementException;
-/**
- * Iterator allowing to explore a graph in a depth-first way.
- *
- * @complexity O(n+m) with n the number of nodes and m the number of edges.
- * @since 20040730
- */
public class DepthFirstIterator<T extends Node> implements Iterator<T> {
- // Attributes
+ boolean directed;
+ Graph graph;
- /**
- * Respect the edge orientation?.
- */
- protected boolean directed = true;
+ Node[] parent;
+ Iterator<Edge>[] iterator;
+ int depth[];
+ Node next;
+ int maxDepth;
- /**
- * Set of already explored nodes.
- */
- protected HashSet<T> closed = new HashSet<T>();
-
- /**
- * Nodes remaining to process. The iteration continues as long as this array
- * is not empty.
- */
- protected LinkedList<T> lifo = new LinkedList<T>();
-
- // Constructors
-
- /**
- * New breadth-first iterator starting at the given start node.
- *
- * @param startNode
- * The node where the graph exploration begins.
- */
- public DepthFirstIterator(Node startNode) {
- this(startNode, true);
- }
-
- /**
- * New breadth-first iterator starting at the given start node.
- *
- * @param startNode
- * The node where the graph exploration begins.
- * @param directed
- * If true the iterator respects the edge direction (the
- * default).
- */
@SuppressWarnings("unchecked")
public DepthFirstIterator(Node startNode, boolean directed) {
- lifo.add((T)startNode);
- closed.add((T)startNode);
this.directed = directed;
+ graph = startNode.getGraph();
+ int n = graph.getNodeCount();
+ parent = new Node[n];
+ iterator = new Iterator[n];
+ depth = new int[n];
+
+ int s = startNode.getIndex();
+ for (int i = 0; i < n; i++)
+ depth[i] = i == s ? 0 : -1;
+ next = startNode;
}
- // Accessors
-
- /**
- * Is this iterator respecting edge orientation ?.
- *
- * @return True if edge orientation is respected (the default).
- */
- public boolean isDirected() {
- return directed;
+ protected void gotoNext() {
+ while (next != null) {
+ int i = next.getIndex();
+ while (iterator[i].hasNext()) {
+ Node neighbor = iterator[i].next().getOpposite(next);
+ int j = neighbor.getIndex();
+ if (iterator[j] == null) {
+ parent[j] = next;
+ iterator[j] = directed ? neighbor.getLeavingEdgeIterator()
+ : neighbor.getEnteringEdgeIterator();
+ depth[j] = depth[i] + 1;
+ if (depth[j] > maxDepth)
+ maxDepth = depth[j];
+ next = neighbor;
+ return;
+ }
+ }
+ next = parent[i];
+ }
}
- /**
- * Is the given node tabu?.
- *
- * @param node
- * The node to test.
- * @return True if tabu.
- */
- protected boolean tabu(T node) {
- return (closed.contains(node));
+ public DepthFirstIterator(Node startNode) {
+ this(startNode, true);
}
- /**
- * Is there a next node to process?.
- *
- * @return True if it remains nodes.
- */
public boolean hasNext() {
- return lifo.size() > 0;
+ return next != null;
}
- /**
- * Next node to process.
- *
- * @return The next node.
- */
- public T next() throws NoSuchElementException {
- if (lifo.size() > 0) {
- T next = lifo.removeLast();
-
- closed.add(next);
- while (lifo.remove(next))
- ;
-
- addNeighborsOf(next);
-
- return next;
- } else {
- throw new NoSuchElementException("no more elements in iterator");
- }
+ @SuppressWarnings("unchecked")
+ public T next() {
+ if (next == null)
+ throw new NoSuchElementException();
+ iterator[next.getIndex()] = directed ? next.getLeavingEdgeIterator()
+ : next.getEnteringEdgeIterator();
+ Node previous = next;
+ gotoNext();
+ return (T) previous;
}
- /**
- * Append the neighbors of the given node (excepted nodes already processed)
- * in the list of nodes to process next.
- *
- * @param node
- * The nodes the neighbors are to be processed.
- */
- protected void addNeighborsOf(T node) {
- Iterator<? extends Edge> k;
-
- if (directed)
- k = node.getLeavingEdgeIterator();
- else
- k = node.getEdgeIterator();
+ public void remove() {
+ throw new UnsupportedOperationException(
+ "This iterator does not support remove");
+ }
- while (k.hasNext()) {
- Edge edge = k.next();
- T adj = edge.getOpposite(node);
+ public int getDepthOf(Node node) {
+ return depth[node.getIndex()];
+ }
- if (!tabu(adj)) {
- lifo.add(adj);
- }
- }
+ public int getDepthMax() {
+ return maxDepth;
}
- // Commands
+ public boolean tabu(Node node) {
+ return depth[node.getIndex()] != -1;
+ }
- /**
- * Unsupported with this iterator.
- */
- public void remove() throws UnsupportedOperationException,
- IllegalStateException {
- throw new UnsupportedOperationException(
- "cannot remove a node using this iterator (yet)");
+ public boolean isDirected() {
+ return directed;
}
-}
+}
View
91 src/org/graphstream/graph/DepthFirstIteratorIndexed.java
@@ -1,91 +0,0 @@
-package org.graphstream.graph;
-
-import java.util.Iterator;
-import java.util.NoSuchElementException;
-
-public class DepthFirstIteratorIndexed<T extends Node> implements Iterator<T> {
- boolean directed;
- Graph graph;
-
- Node[] parent;
- Iterator<Edge>[] iterator;
- int depth[];
- Node next;
- int maxDepth;
-
- @SuppressWarnings("unchecked")
- public DepthFirstIteratorIndexed(Node startNode, boolean directed) {
- this.directed = directed;
- graph = startNode.getGraph();
- int n = graph.getNodeCount();
- parent = new Node[n];
- iterator = new Iterator[n];
- depth = new int[n];
-
- int s = startNode.getIndex();
- for (int i = 0; i < n; i++)
- depth[i] = i == s ? 0 : -1;
- next = startNode;
- }
-
- protected void gotoNext() {
- while (next != null) {
- int i = next.getIndex();
- while (iterator[i].hasNext()) {
- Node neighbor = iterator[i].next().getOpposite(next);
- int j = neighbor.getIndex();
- if (iterator[j] == null) {
- parent[j] = next;
- iterator[j] = directed ? neighbor.getLeavingEdgeIterator()
- : neighbor.getEnteringEdgeIterator();
- depth[j] = depth[i] + 1;
- if (depth[j] > maxDepth)
- maxDepth = depth[j];
- next = neighbor;
- return;
- }
- }
- next = parent[i];
- }
- }
-
- public DepthFirstIteratorIndexed(Node startNode) {
- this(startNode, true);
- }
-
- public boolean hasNext() {
- return next != null;
- }
-
- @SuppressWarnings("unchecked")
- public T next() {
- if (next == null)
- throw new NoSuchElementException();
- iterator[next.getIndex()] = directed ? next.getLeavingEdgeIterator()
- : next.getEnteringEdgeIterator();
- Node previous = next;
- gotoNext();
- return (T) previous;
- }
-
- public void remove() {
- throw new UnsupportedOperationException(
- "This iterator does not support remove");
- }
-
- public int getDepthOf(Node node) {
- return depth[node.getIndex()];
- }
-
- public int getMaxDepth() {
- return maxDepth;
- }
-
- public boolean isTabu(Node node) {
- return depth[node.getIndex()] != -1;
- }
-
- public boolean isDirected() {
- return directed;
- }
-}
View
12 src/org/graphstream/graph/implementations/AbstractNode.java
@@ -6,8 +6,8 @@
import java.util.Iterator;
import java.util.NoSuchElementException;
-import org.graphstream.graph.BreadthFirstIteratorIndexed;
-import org.graphstream.graph.DepthFirstIteratorIndexed;
+import org.graphstream.graph.BreadthFirstIterator;
+import org.graphstream.graph.DepthFirstIterator;
import org.graphstream.graph.Edge;
import org.graphstream.graph.Graph;
import org.graphstream.graph.Node;
@@ -461,7 +461,7 @@ public void remove() {
public <T extends Node> Iterator<T> getBreadthFirstIterator() {
// XXX change it when the old iterator disappears
// XXX change the return type to have access to the other methods
- return new BreadthFirstIteratorIndexed<T>(this);
+ return new BreadthFirstIterator<T>(this);
}
/**
@@ -473,7 +473,7 @@ public void remove() {
public <T extends Node> Iterator<T> getBreadthFirstIterator(boolean directed) {
// XXX change it when the old iterator disappears
// XXX change the return type to have access to the other methods
- return new BreadthFirstIteratorIndexed<T>(this, directed);
+ return new BreadthFirstIterator<T>(this, directed);
}
/**
@@ -485,7 +485,7 @@ public void remove() {
public <T extends Node> Iterator<T> getDepthFirstIterator() {
// XXX change it when the old iterator disappears
// XXX change the return type to have access to the other methods
- return new DepthFirstIteratorIndexed<T>(this);
+ return new DepthFirstIterator<T>(this);
}
/**
@@ -497,7 +497,7 @@ public void remove() {
public <T extends Node> Iterator<T> getDepthFirstIterator(boolean directed) {
// XXX change it when the old iterator disappears
// XXX change the return type to have access to the other methods
- return new DepthFirstIteratorIndexed<T>(this, directed);
+ return new DepthFirstIterator<T>(this, directed);
}
// *** Other methods ***

0 comments on commit 70ec71e

Please sign in to comment.
Something went wrong with that request. Please try again.