001/*
002 * Copyright (C) 2012 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.collect;
018
019import static com.google.common.base.Preconditions.checkNotNull;
020
021import com.google.common.annotations.Beta;
022import com.google.common.annotations.GwtCompatible;
023
024import java.util.ArrayDeque;
025import java.util.Deque;
026import java.util.Iterator;
027import java.util.Queue;
028
029/**
030 * Views elements of a type {@code T} as nodes in a tree, and provides methods to traverse the trees
031 * induced by this traverser.
032 *
033 * <p>For example, the tree
034 *
035 * <pre>          {@code
036 *          h
037 *        / | \
038 *       /  e  \
039 *      d       g
040 *     /|\      |
041 *    / | \     f
042 *   a  b  c       }</pre>
043 *
044 * <p>can be iterated over in preorder (hdabcegf), postorder (abcdefgh), or breadth-first order
045 * (hdegabcf).
046 *
047 * <p>Null nodes are strictly forbidden.
048 *
049 * @author Louis Wasserman
050 * @since 15.0
051 */
052@Beta
053@GwtCompatible(emulated = true)
054public abstract class TreeTraverser<T> {
055  // TODO(user): make this GWT-compatible when we've checked in ArrayDeque emulation
056
057  /**
058   * Returns the children of the specified node.  Must not contain null.
059   */
060  public abstract Iterable<T> children(T root);
061
062  /**
063   * Returns an unmodifiable iterable over the nodes in a tree structure, using pre-order
064   * traversal. That is, each node's subtrees are traversed after the node itself is returned.
065   *
066   * <p>No guarantees are made about the behavior of the traversal when nodes change while
067   * iteration is in progress or when the iterators generated by {@link #children} are advanced.
068   */
069  public final FluentIterable<T> preOrderTraversal(final T root) {
070    checkNotNull(root);
071    return new FluentIterable<T>() {
072      @Override
073      public UnmodifiableIterator<T> iterator() {
074        return preOrderIterator(root);
075      }
076    };
077  }
078
079  // overridden in BinaryTreeTraverser
080  UnmodifiableIterator<T> preOrderIterator(T root) {
081    return new PreOrderIterator(root);
082  }
083
084  private final class PreOrderIterator extends UnmodifiableIterator<T> {
085    private final Deque<Iterator<T>> stack;
086
087    PreOrderIterator(T root) {
088      this.stack = new ArrayDeque<Iterator<T>>();
089      stack.addLast(Iterators.singletonIterator(checkNotNull(root)));
090    }
091
092    @Override
093    public boolean hasNext() {
094      return !stack.isEmpty();
095    }
096
097    @Override
098    public T next() {
099      Iterator<T> itr = stack.getLast(); // throws NSEE if empty
100      T result = checkNotNull(itr.next());
101      if (!itr.hasNext()) {
102        stack.removeLast();
103      }
104      Iterator<T> childItr = children(result).iterator();
105      if (childItr.hasNext()) {
106        stack.addLast(childItr);
107      }
108      return result;
109    }
110  }
111
112  /**
113   * Returns an unmodifiable iterable over the nodes in a tree structure, using post-order
114   * traversal. That is, each node's subtrees are traversed before the node itself is returned.
115   *
116   * <p>No guarantees are made about the behavior of the traversal when nodes change while
117   * iteration is in progress or when the iterators generated by {@link #children} are advanced.
118   */
119  public final FluentIterable<T> postOrderTraversal(final T root) {
120    checkNotNull(root);
121    return new FluentIterable<T>() {
122      @Override
123      public UnmodifiableIterator<T> iterator() {
124        return postOrderIterator(root);
125      }
126    };
127  }
128
129  // overridden in BinaryTreeTraverser
130  UnmodifiableIterator<T> postOrderIterator(T root) {
131    return new PostOrderIterator(root);
132  }
133
134  private static final class PostOrderNode<T> {
135    final T root;
136    final Iterator<T> childIterator;
137
138    PostOrderNode(T root, Iterator<T> childIterator) {
139      this.root = checkNotNull(root);
140      this.childIterator = checkNotNull(childIterator);
141    }
142  }
143
144  private final class PostOrderIterator extends AbstractIterator<T> {
145    private final ArrayDeque<PostOrderNode<T>> stack;
146
147    PostOrderIterator(T root) {
148      this.stack = new ArrayDeque<PostOrderNode<T>>();
149      stack.addLast(expand(root));
150    }
151
152    @Override
153    protected T computeNext() {
154      while (!stack.isEmpty()) {
155        PostOrderNode<T> top = stack.getLast();
156        if (top.childIterator.hasNext()) {
157          T child = top.childIterator.next();
158          stack.addLast(expand(child));
159        } else {
160          stack.removeLast();
161          return top.root;
162        }
163      }
164      return endOfData();
165    }
166
167    private PostOrderNode<T> expand(T t) {
168      return new PostOrderNode<T>(t, children(t).iterator());
169    }
170  }
171
172  /**
173   * Returns an unmodifiable iterable over the nodes in a tree structure, using breadth-first
174   * traversal. That is, all the nodes of depth 0 are returned, then depth 1, then 2, and so on.
175   *
176   * <p>No guarantees are made about the behavior of the traversal when nodes change while
177   * iteration is in progress or when the iterators generated by {@link #children} are advanced.
178   */
179  public final FluentIterable<T> breadthFirstTraversal(final T root) {
180    checkNotNull(root);
181    return new FluentIterable<T>() {
182      @Override
183      public UnmodifiableIterator<T> iterator() {
184        return new BreadthFirstIterator(root);
185      }
186    };
187  }
188
189  private final class BreadthFirstIterator extends UnmodifiableIterator<T>
190      implements PeekingIterator<T> {
191    private final Queue<T> queue;
192
193    BreadthFirstIterator(T root) {
194      this.queue = new ArrayDeque<T>();
195      queue.add(root);
196    }
197
198    @Override
199    public boolean hasNext() {
200      return !queue.isEmpty();
201    }
202
203    @Override
204    public T peek() {
205      return queue.element();
206    }
207
208    @Override
209    public T next() {
210      T result = queue.remove();
211      Iterables.addAll(queue, children(result));
212      return result;
213    }
214  }
215}