Java tutorial
/* * Copyright (c) 2001, Zoltan Farkas All Rights Reserved. * * 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 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, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ package org.spf4j.ds; import com.google.common.collect.Sets; import java.util.ArrayDeque; import java.util.Collection; import java.util.Deque; import java.util.HashSet; import java.util.Map; import java.util.PriorityQueue; import java.util.Queue; import java.util.Set; /** * * @author zoly */ public final class Traversals { private Traversals() { } public interface TraversalCallback<V, E> { void handle(V vertex, Map<E, V> edges); } public static <V, E> void traverse(final Graph<V, E> graph, final V startNode, final TraversalCallback<V, E> handler, final boolean isBreadth) { Set<V> traversedNodes = new HashSet<V>(); Deque<V> traversalQueue = new ArrayDeque<V>(); traversalQueue.add(startNode); boolean done = false; do { boolean first = true; while (!traversalQueue.isEmpty()) { V node; if (isBreadth) { node = traversalQueue.removeFirst(); } else { node = traversalQueue.removeLast(); } VertexEdges<V, E> edges = graph.getEdges(node); if (traversedNodes.contains(node)) { continue; } Map<E, V> incomming = edges.getIncomming(); boolean hasIncomingBeenTraversed = true; for (V val : incomming.values()) { if (!traversedNodes.contains(val)) { hasIncomingBeenTraversed = false; break; } } if (!first && !hasIncomingBeenTraversed) { continue; } handler.handle(node, incomming); traversedNodes.add(node); first = false; Map<E, V> outgoing = edges.getOutgoing(); for (V next : outgoing.values()) { traversalQueue.add(next); } } Set<V> leftNodes = Sets.difference(graph.getVertices(), traversedNodes); if (leftNodes.isEmpty()) { done = true; } else { boolean added = false; for (V node : leftNodes) { Collection<V> incomingNodes = graph.getEdges(node).getIncomming().values(); for (V incoming : incomingNodes) { if (traversedNodes.contains(incoming)) { traversalQueue.add(node); added = true; break; } } if (added) { break; } } } } while (!done); } public static final class VertexHolder<V> implements Comparable<VertexHolder<V>> { private final V vertex; private final int order; private final int nrImcoming; public VertexHolder(final V vertex, final int order, final int nrImcoming) { this.vertex = vertex; this.order = order; this.nrImcoming = nrImcoming; } @Override public int compareTo(final VertexHolder<V> o) { int result = this.nrImcoming - o.nrImcoming; if (result == 0) { return this.order - o.order; } else { return result; } } public V getVertex() { return vertex; } @Override public int hashCode() { int hash = 7; hash = 29 * hash + (this.vertex != null ? this.vertex.hashCode() : 0); hash = 29 * hash + this.order; return 29 * hash + this.nrImcoming; } @Override public boolean equals(final Object obj) { if (obj == null) { return false; } if (getClass() != obj.getClass()) { return false; } final VertexHolder<V> other = (VertexHolder<V>) obj; return (this.compareTo(other) == 0); } } public static <V, E> void customTraverse(final Graph<V, E> graph, final V startNode, final TraversalCallback<V, E> handler) { Set<V> traversedNodes = new HashSet<V>(); Queue<VertexHolder<V>> traversalQueue = new PriorityQueue<VertexHolder<V>>(16); int counter = 0; traversalQueue.add(new VertexHolder<V>(startNode, counter++, 0)); boolean done = false; do { boolean first = true; while (!traversalQueue.isEmpty()) { V node = traversalQueue.remove().getVertex(); VertexEdges<V, E> edges = graph.getEdges(node); if (traversedNodes.contains(node)) { continue; } Map<E, V> incomming = edges.getIncomming(); boolean hasIncomingBeenTraversed = true; for (V val : incomming.values()) { if (!traversedNodes.contains(val)) { hasIncomingBeenTraversed = false; break; } } if (!first && !hasIncomingBeenTraversed) { continue; } handler.handle(node, incomming); traversedNodes.add(node); first = false; Map<E, V> outgoing = edges.getOutgoing(); for (V next : outgoing.values()) { traversalQueue .add(new VertexHolder<V>(next, counter++, graph.getEdges(next).getIncomming().size())); } } Set<V> leftNodes = Sets.difference(graph.getVertices(), traversedNodes); if (leftNodes.isEmpty()) { done = true; } else { boolean added = false; for (V node : leftNodes) { Collection<V> incomingNodes = graph.getEdges(node).getIncomming().values(); for (V incoming : incomingNodes) { if (traversedNodes.contains(incoming)) { traversalQueue.add(new VertexHolder<V>(node, counter++, 0)); added = true; break; } } if (added) { break; } } } } while (!done); } }