001/*
002 * Copyright (C) 2017 The Guava Authors
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016
017package com.google.common.graph;
018
019import static com.google.common.base.Preconditions.checkArgument;
020import static com.google.common.base.Preconditions.checkNotNull;
021import static com.google.common.collect.Iterators.singletonIterator;
022
023import com.google.common.annotations.Beta;
024import com.google.common.collect.AbstractIterator;
025import com.google.common.collect.Iterables;
026import com.google.common.collect.UnmodifiableIterator;
027import java.util.ArrayDeque;
028import java.util.Deque;
029import java.util.HashSet;
030import java.util.Iterator;
031import java.util.Queue;
032import java.util.Set;
033
034/**
035 * Provides methods for traversing a graph.
036 *
037 * @author Jens Nyman
038 * @param <N> Node parameter type
039 * @since 23.1
040 */
041@Beta
042public abstract class Traverser<N> {
043
044  /**
045   * Creates a new traverser for the given general {@code graph}.
046   *
047   * <p>If {@code graph} is known to be tree-shaped, consider using {@link
048   * #forTree(SuccessorsFunction)} instead.
049   *
050   * <p><b>Performance notes</b>
051   *
052   * <ul>
053   *   <li>Traversals require <i>O(n)</i> time (where <i>n</i> is the number of nodes reachable from
054   *       the start node), assuming that the node objects have <i>O(1)</i> {@code equals()} and
055   *       {@code hashCode()} implementations.
056   *   <li>While traversing, the traverser will use <i>O(n)</i> space (where <i>n</i> is the number
057   *       of nodes that have thus far been visited), plus <i>O(H)</i> space (where <i>H</i> is the
058   *       number of nodes that have been seen but not yet visited, that is, the "horizon").
059   * </ul>
060   *
061   * @param graph {@link SuccessorsFunction} representing a general graph that may have cycles.
062   */
063  public static <N> Traverser<N> forGraph(SuccessorsFunction<N> graph) {
064    checkNotNull(graph);
065    return new GraphTraverser<>(graph);
066  }
067
068  /**
069   * Creates a new traverser for a directed acyclic graph that has at most one path from the start
070   * node to any node reachable from the start node, such as a tree.
071   *
072   * <p>Providing graphs that don't conform to the above description may lead to:
073   *
074   * <ul>
075   *   <li>Traversal not terminating (if the graph has cycles)
076   *   <li>Nodes being visited multiple times (if multiple paths exist from the start node to any
077   *       node reachable from it)
078   * </ul>
079   *
080   * In these cases, use {@link #forGraph(SuccessorsFunction)} instead.
081   *
082   * <p><b>Performance notes</b>
083   *
084   * <ul>
085   *   <li>Traversals require <i>O(n)</i> time (where <i>n</i> is the number of nodes reachable from
086   *       the start node).
087   *   <li>While traversing, the traverser will use <i>O(H)</i> space (where <i>H</i> is the number
088   *       of nodes that have been seen but not yet visited, that is, the "horizon").
089   * </ul>
090   *
091   * <p><b>Examples</b>
092   *
093   * <p>This is a valid input graph (all edges are directed facing downwards):
094   *
095   * <pre>{@code
096   *    a     b      c
097   *   / \   / \     |
098   *  /   \ /   \    |
099   * d     e     f   g
100   *       |
101   *       |
102   *       h
103   * }</pre>
104   *
105   * <p>This is <b>not</b> a valid input graph (all edges are directed facing downwards):
106   *
107   * <pre>{@code
108   *    a     b
109   *   / \   / \
110   *  /   \ /   \
111   * c     d     e
112   *        \   /
113   *         \ /
114   *          f
115   * }</pre>
116   *
117   * <p>because there are two paths from {@code b} to {@code f} ({@code b->d->f} and {@code
118   * b->e->f}).
119   *
120   * <p><b>Note on binary trees</b>
121   *
122   * <p>This method can be used to traverse over a binary tree. Given methods {@code
123   * leftChild(node)} and {@code rightChild(node)}, this method can be called as
124   *
125   * <pre>{@code
126   * Traverser.forTree(node -> ImmutableList.of(leftChild(node), rightChild(node)));
127   * }</pre>
128   *
129   * @param tree {@link SuccessorsFunction} representing a directed acyclic graph that has at most
130   *     one path between any two nodes
131   */
132  public static <N> Traverser<N> forTree(SuccessorsFunction<N> tree) {
133    checkNotNull(tree);
134    if (tree instanceof BaseGraph) {
135      checkArgument(((BaseGraph<?>) tree).isDirected(), "Undirected graphs can never be trees.");
136    }
137    if (tree instanceof Network) {
138      checkArgument(((Network<?, ?>) tree).isDirected(), "Undirected networks can never be trees.");
139    }
140    return new TreeTraverser<>(tree);
141  }
142
143  /**
144   * Returns an unmodifiable {@code Iterable} over the nodes reachable from {@code startNode}, in
145   * the order of a breadth-first traversal. That is, all the nodes of depth 0 are returned, then
146   * depth 1, then 2, and so on.
147   *
148   * <p><b>Example:</b> The following graph with {@code startNode} {@code a} would return nodes in
149   * the order {@code abcdef} (assuming successors are returned in alphabetical order).
150   *
151   * <pre>{@code
152   * b ---- a ---- d
153   * |      |
154   * |      |
155   * e ---- c ---- f
156   * }</pre>
157   *
158   * <p>The behavior of this method is undefined if the nodes, or the topology of the graph, change
159   * while iteration is in progress.
160   *
161   * <p>The returned {@code Iterable} can be iterated over multiple times. Every iterator will
162   * compute its next element on the fly. It is thus possible to limit the traversal to a certain
163   * number of nodes as follows:
164   *
165   * <pre>{@code
166   * Iterables.limit(Traverser.forGraph(graph).breadthFirst(node), maxNumberOfNodes);
167   * }</pre>
168   *
169   * <p>See <a href="https://en.wikipedia.org/wiki/Breadth-first_search">Wikipedia</a> for more
170   * info.
171   */
172  public abstract Iterable<N> breadthFirst(N startNode);
173
174  /**
175   * Returns an unmodifiable {@code Iterable} over the nodes reachable from {@code startNode}, in
176   * the order of a depth-first pre-order traversal. "Pre-order" implies that nodes appear in the
177   * {@code Iterable} in the order in which they are first visited.
178   *
179   * <p><b>Example:</b> The following graph with {@code startNode} {@code a} would return nodes in
180   * the order {@code abecfd} (assuming successors are returned in alphabetical order).
181   *
182   * <pre>{@code
183   * b ---- a ---- d
184   * |      |
185   * |      |
186   * e ---- c ---- f
187   * }</pre>
188   *
189   * <p>The behavior of this method is undefined if the nodes, or the topology of the graph, change
190   * while iteration is in progress.
191   *
192   * <p>The returned {@code Iterable} can be iterated over multiple times. Every iterator will
193   * compute its next element on the fly. It is thus possible to limit the traversal to a certain
194   * number of nodes as follows:
195   *
196   * <pre>{@code
197   * Iterables.limit(
198   *     Traverser.forGraph(graph).depthFirstPreOrder(node), maxNumberOfNodes);
199   * }</pre>
200   *
201   * <p>See <a href="https://en.wikipedia.org/wiki/Depth-first_search">Wikipedia</a> for more info.
202   */
203  public abstract Iterable<N> depthFirstPreOrder(N startNode);
204
205  /**
206   * Returns an unmodifiable {@code Iterable} over the nodes reachable from {@code startNode}, in
207   * the order of a depth-first post-order traversal. "Post-order" implies that nodes appear in the
208   * {@code Iterable} in the order in which they are visited for the last time.
209   *
210   * <p><b>Example:</b> The following graph with {@code startNode} {@code a} would return nodes in
211   * the order {@code fcebda} (assuming successors are returned in alphabetical order).
212   *
213   * <pre>{@code
214   * b ---- a ---- d
215   * |      |
216   * |      |
217   * e ---- c ---- f
218   * }</pre>
219   *
220   * <p>The behavior of this method is undefined if the nodes, or the topology of the graph, change
221   * while iteration is in progress.
222   *
223   * <p>The returned {@code Iterable} can be iterated over multiple times. Every iterator will
224   * compute its next element on the fly. It is thus possible to limit the traversal to a certain
225   * number of nodes as follows:
226   *
227   * <pre>{@code
228   * Iterables.limit(
229   *     Traverser.forGraph(graph).depthFirstPostOrder(node), maxNumberOfNodes);
230   * }</pre>
231   *
232   * <p>See <a href="https://en.wikipedia.org/wiki/Depth-first_search">Wikipedia</a> for more info.
233   */
234  public abstract Iterable<N> depthFirstPostOrder(N startNode);
235
236  private static final class GraphTraverser<N> extends Traverser<N> {
237    private final SuccessorsFunction<N> graph;
238
239    GraphTraverser(SuccessorsFunction<N> graph) {
240      this.graph = checkNotNull(graph);
241    }
242
243    @Override
244    public Iterable<N> breadthFirst(final N startNode) {
245      return new Iterable<N>() {
246        @Override
247        public Iterator<N> iterator() {
248          return new BreadthFirstIterator(startNode);
249        }
250      };
251    }
252
253    @Override
254    public Iterable<N> depthFirstPreOrder(final N startNode) {
255      return new Iterable<N>() {
256        @Override
257        public Iterator<N> iterator() {
258          return new DepthFirstIterator(startNode, Order.PREORDER);
259        }
260      };
261    }
262
263    @Override
264    public Iterable<N> depthFirstPostOrder(final N startNode) {
265      return new Iterable<N>() {
266        @Override
267        public Iterator<N> iterator() {
268          return new DepthFirstIterator(startNode, Order.POSTORDER);
269        }
270      };
271    }
272
273    private final class BreadthFirstIterator extends UnmodifiableIterator<N> {
274      private final Queue<N> queue = new ArrayDeque<>();
275      private final Set<N> visited = new HashSet<>();
276
277      BreadthFirstIterator(N root) {
278        queue.add(root);
279        visited.add(root);
280      }
281
282      @Override
283      public boolean hasNext() {
284        return !queue.isEmpty();
285      }
286
287      @Override
288      public N next() {
289        N current = queue.remove();
290        for (N neighbor : graph.successors(current)) {
291          if (visited.add(neighbor)) {
292            queue.add(neighbor);
293          }
294        }
295        return current;
296      }
297    }
298
299    private final class DepthFirstIterator extends AbstractIterator<N> {
300      private final Deque<NodeAndSuccessors> stack = new ArrayDeque<>();
301      private final Set<N> visited = new HashSet<>();
302      private final Order order;
303
304      DepthFirstIterator(N root, Order order) {
305        // our invariant is that in computeNext we call next on the iterator at the top first, so we
306        // need to start with one additional item on that iterator
307        stack.push(withSuccessors(root));
308        this.order = order;
309      }
310
311      @Override
312      protected N computeNext() {
313        while (true) {
314          if (stack.isEmpty()) {
315            return endOfData();
316          }
317          NodeAndSuccessors node = stack.getFirst();
318          boolean firstVisit = visited.add(node.node);
319          boolean lastVisit = !node.successorIterator.hasNext();
320          boolean produceNode =
321              (firstVisit && order == Order.PREORDER) || (lastVisit && order == Order.POSTORDER);
322          if (lastVisit) {
323            stack.pop();
324          } else {
325            // we need to push a neighbor, but only if we haven't already seen it
326            N successor = node.successorIterator.next();
327            if (!visited.contains(successor)) {
328              stack.push(withSuccessors(successor));
329            }
330          }
331          if (produceNode) {
332            return node.node;
333          }
334        }
335      }
336
337      NodeAndSuccessors withSuccessors(N node) {
338        return new NodeAndSuccessors(node, graph.successors(node));
339      }
340
341      /** A simple tuple of a node and a partially iterated {@link Iterator} of its successors. */
342      private final class NodeAndSuccessors {
343        final N node;
344        final Iterator<? extends N> successorIterator;
345
346        NodeAndSuccessors(N node, Iterable<? extends N> successors) {
347          this.node = node;
348          this.successorIterator = successors.iterator();
349        }
350      }
351    }
352  }
353
354  private static final class TreeTraverser<N> extends Traverser<N> {
355    private final SuccessorsFunction<N> tree;
356
357    TreeTraverser(SuccessorsFunction<N> tree) {
358      this.tree = checkNotNull(tree);
359    }
360
361    @Override
362    public Iterable<N> breadthFirst(final N startNode) {
363      return new Iterable<N>() {
364        @Override
365        public Iterator<N> iterator() {
366          return new BreadthFirstIterator(startNode);
367        }
368      };
369    }
370
371    @Override
372    public Iterable<N> depthFirstPreOrder(final N startNode) {
373      return new Iterable<N>() {
374        @Override
375        public Iterator<N> iterator() {
376          return new DepthFirstPreOrderIterator(startNode);
377        }
378      };
379    }
380
381    @Override
382    public Iterable<N> depthFirstPostOrder(final N startNode) {
383      return new Iterable<N>() {
384        @Override
385        public Iterator<N> iterator() {
386          return new DepthFirstPostOrderIterator(startNode);
387        }
388      };
389    }
390
391    private final class BreadthFirstIterator extends UnmodifiableIterator<N> {
392      private final Queue<N> queue = new ArrayDeque<>();
393
394      BreadthFirstIterator(N root) {
395        queue.add(root);
396      }
397
398      @Override
399      public boolean hasNext() {
400        return !queue.isEmpty();
401      }
402
403      @Override
404      public N next() {
405        N current = queue.remove();
406        Iterables.addAll(queue, tree.successors(current));
407        return current;
408      }
409    }
410
411    private final class DepthFirstPreOrderIterator extends UnmodifiableIterator<N> {
412      private final Deque<Iterator<? extends N>> stack = new ArrayDeque<>();
413
414      DepthFirstPreOrderIterator(N root) {
415        stack.addLast(singletonIterator(checkNotNull(root)));
416      }
417
418      @Override
419      public boolean hasNext() {
420        return !stack.isEmpty();
421      }
422
423      @Override
424      public N next() {
425        Iterator<? extends N> iterator = stack.getLast(); // throws NoSuchElementException if empty
426        N result = checkNotNull(iterator.next());
427        if (!iterator.hasNext()) {
428          stack.removeLast();
429        }
430        Iterator<? extends N> childIterator = tree.successors(result).iterator();
431        if (childIterator.hasNext()) {
432          stack.addLast(childIterator);
433        }
434        return result;
435      }
436    }
437
438    private final class DepthFirstPostOrderIterator extends AbstractIterator<N> {
439      private final ArrayDeque<NodeAndChildren> stack = new ArrayDeque<>();
440
441      DepthFirstPostOrderIterator(N root) {
442        stack.addLast(withChildren(root));
443      }
444
445      @Override
446      protected N computeNext() {
447        while (!stack.isEmpty()) {
448          NodeAndChildren top = stack.getLast();
449          if (top.childIterator.hasNext()) {
450            N child = top.childIterator.next();
451            stack.addLast(withChildren(child));
452          } else {
453            stack.removeLast();
454            return top.node;
455          }
456        }
457        return endOfData();
458      }
459
460      NodeAndChildren withChildren(N node) {
461        return new NodeAndChildren(node, tree.successors(node));
462      }
463
464      /** A simple tuple of a node and a partially iterated {@link Iterator} of its children. */
465      private final class NodeAndChildren {
466        final N node;
467        final Iterator<? extends N> childIterator;
468
469        NodeAndChildren(N node, Iterable<? extends N> children) {
470          this.node = node;
471          this.childIterator = children.iterator();
472        }
473      }
474    }
475  }
476
477  private enum Order {
478    PREORDER,
479    POSTORDER
480  }
481}