Class Traverser<T>

java.lang.Object
com.landawn.abacus.guava.Traverser<T>
Type Parameters:
T - Node parameter type

public final class Traverser<T> extends Object
Provides methods for traversing a graph.
See Also:
  • Field Summary

    Fields
    Modifier and Type
    Field
    Description
    static final Traverser<File>
     
  • Method Summary

    Modifier and Type
    Method
    Description
    breadthFirst(T startNode)
    Returns an unmodifiable Iterable over the nodes reachable from startNode, in the order of a breadth-first traversal.
    Returns an unmodifiable Iterable over the nodes reachable from startNode, in the order of a depth-first post-order traversal.
    depthFirstPreOrder(T startNode)
    Returns an unmodifiable Iterable over the nodes reachable from startNode, in the order of a depth-first pre-order traversal.
    static <T> Traverser<T>
    forGraph(Function<? super T,Iterable<? extends T>> graph)
    Creates a new traverser for the given general graph.
    static <T> Traverser<T>
    forTree(Function<? super T,Iterable<? extends T>> tree)
    Creates a new traverser for a directed acyclic graph that has at most one path from the start node to any node reachable from the start node, such as a tree.

    Methods inherited from class java.lang.Object

    equals, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
  • Field Details

  • Method Details

    • forTree

      public static <T> Traverser<T> forTree(Function<? super T,Iterable<? extends T>> tree)
      Creates a new traverser for a directed acyclic graph that has at most one path from the start node to any node reachable from the start node, such as a tree.

      Providing graphs that don't conform to the above description may lead to:

      • Traversal not terminating (if the graph has cycles)
      • Nodes being visited multiple times (if multiple paths exist from the start node to any node reachable from it)
      In these cases, use
      invalid @link
      #forGraph(SuccessorsFunction)
      instead.

      Performance notes

      • Traversals require O(n) time (where n is the number of nodes reachable from the start node).
      • While traversing, the traverser will use O(H) space (where H is the number of nodes that have been seen but not yet visited, that is, the "horizon").

      Examples

      This is a valid input graph (all edges are directed facing downwards):

      
          a     b      c
         / \   / \     |
        /   \ /   \    |
       d     e     f   g
             |
             |
             h
       

      This is not a valid input graph (all edges are directed facing downwards):

      
          a     b
         / \   / \
        /   \ /   \
       c     d     e
              \   /
               \ /
                f
       

      because there are two paths from b to f (b->d->f and b->e->f).

      Note on binary trees

      This method can be used to traverse over a binary tree. Given methods leftChild(node) and rightChild(node), this method can be called as

      
       Traverser.forTree(node -> ImmutableList.of(leftChild(node), rightChild(node)));
       
      Type Parameters:
      T -
      Parameters:
      tree - SuccessorsFunction representing a directed acyclic graph that has at most one path between any two nodes
      Returns:
    • forGraph

      public static <T> Traverser<T> forGraph(Function<? super T,Iterable<? extends T>> graph)
      Creates a new traverser for the given general graph.

      If graph is known to be tree-shaped, consider using

      invalid @link
      #forTree(SuccessorsFunction)
      instead.

      Performance notes

      • Traversals require O(n) time (where n is the number of nodes reachable from the start node), assuming that the node objects have O(1) equals() and hashCode() implementations.
      • While traversing, the traverser will use O(n) space (where n is the number of nodes that have thus far been visited), plus O(H) space (where H is the number of nodes that have been seen but not yet visited, that is, the "horizon").
      Type Parameters:
      T -
      Parameters:
      graph - SuccessorsFunction representing a general graph that may have cycles.
      Returns:
    • breadthFirst

      public Stream<T> breadthFirst(T startNode)
      Returns an unmodifiable Iterable over the nodes reachable from startNode, in the order of a breadth-first traversal. That is, all the nodes of depth 0 are returned, then depth 1, then 2, and so on.

      Example: The following graph with startNode a would return nodes in the order abcdef (assuming successors are returned in alphabetical order).

      
       b ---- a ---- d
       |      |
       |      |
       e ---- c ---- f
       

      The behavior of this method is undefined if the nodes, or the topology of the graph, change while iteration is in progress.

      The returned Iterable can be iterated over multiple times. Every iterator will compute its next element on the fly. It is thus possible to limit the traversal to a certain number of nodes as follows:

      
       Iterables.limit(Traverser.forGraph(graph).breadthFirst(node), maxNumberOfNodes);
       

      See Wikipedia for more info.

      Parameters:
      startNode -
      Returns:
      Throws:
      IllegalArgumentException - if startNode is not an element of the graph
    • depthFirstPreOrder

      public Stream<T> depthFirstPreOrder(T startNode)
      Returns an unmodifiable Iterable over the nodes reachable from startNode, in the order of a depth-first pre-order traversal. "Pre-order" implies that nodes appear in the Iterable in the order in which they are first visited.

      Example: The following graph with startNode a would return nodes in the order abecfd (assuming successors are returned in alphabetical order).

      
       b ---- a ---- d
       |      |
       |      |
       e ---- c ---- f
       

      The behavior of this method is undefined if the nodes, or the topology of the graph, change while iteration is in progress.

      The returned Iterable can be iterated over multiple times. Every iterator will compute its next element on the fly. It is thus possible to limit the traversal to a certain number of nodes as follows:

      
       Iterables.limit(
           Traverser.forGraph(graph).depthFirstPreOrder(node), maxNumberOfNodes);
       

      See Wikipedia for more info.

      Parameters:
      startNode -
      Returns:
      Throws:
      IllegalArgumentException - if startNode is not an element of the graph
    • depthFirstPostOrder

      public Stream<T> depthFirstPostOrder(T startNode)
      Returns an unmodifiable Iterable over the nodes reachable from startNode, in the order of a depth-first post-order traversal. "Post-order" implies that nodes appear in the Iterable in the order in which they are visited for the last time.

      Example: The following graph with startNode a would return nodes in the order fcebda (assuming successors are returned in alphabetical order).

      
       b ---- a ---- d
       |      |
       |      |
       e ---- c ---- f
       

      The behavior of this method is undefined if the nodes, or the topology of the graph, change while iteration is in progress.

      The returned Iterable can be iterated over multiple times. Every iterator will compute its next element on the fly. It is thus possible to limit the traversal to a certain number of nodes as follows:

      
       Iterables.limit(
           Traverser.forGraph(graph).depthFirstPostOrder(node), maxNumberOfNodes);
       

      See Wikipedia for more info.

      Parameters:
      startNode -
      Returns:
      Throws:
      IllegalArgumentException - if startNode is not an element of the graph