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}