11d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert/*
21d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Copyright (C) 2011 The Guava Authors
31d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *
41d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
51d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * in compliance with the License. You may obtain a copy of the License at
61d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *
71d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * http://www.apache.org/licenses/LICENSE-2.0
81d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *
91d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Unless required by applicable law or agreed to in writing, software distributed under the
101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * express or implied. See the License for the specific language governing permissions and
121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * limitations under the License.
131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert */
141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertpackage com.google.common.collect;
161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport static com.google.common.base.Preconditions.checkNotNull;
181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport com.google.common.annotations.GwtCompatible;
201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport com.google.common.base.Optional;
211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.util.NoSuchElementException;
231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport javax.annotation.Nullable;
251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert/**
271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * A {@code BstPath} supporting inorder traversal operations.
281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *
291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * @author Louis Wasserman
301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert */
311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert@GwtCompatible
321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertfinal class BstInOrderPath<N extends BstNode<?, N>> extends BstPath<N, BstInOrderPath<N>> {
331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * The factory to use to construct {@code BstInOrderPath} values.
351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public static <N extends BstNode<?, N>> BstPathFactory<N, BstInOrderPath<N>> inOrderFactory() {
371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return new BstPathFactory<N, BstInOrderPath<N>>() {
381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      @Override
391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      public BstInOrderPath<N> extension(BstInOrderPath<N> path, BstSide side) {
401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        return BstInOrderPath.extension(path, side);
411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      @Override
441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      public BstInOrderPath<N> initialPath(N root) {
451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        return new BstInOrderPath<N>(root, null, null);
461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    };
481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  private static <N extends BstNode<?, N>> BstInOrderPath<N> extension(
511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      BstInOrderPath<N> path, BstSide side) {
521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    checkNotNull(path);
531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    N tip = path.getTip();
541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return new BstInOrderPath<N>(tip.getChild(side), side, path);
551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  private final BstSide sideExtension;
581d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  private transient Optional<BstInOrderPath<N>> prevInOrder;
591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  private transient Optional<BstInOrderPath<N>> nextInOrder;
601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  private BstInOrderPath(
621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      N tip, @Nullable BstSide sideExtension, @Nullable BstInOrderPath<N> tail) {
631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    super(tip, tail);
641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    this.sideExtension = sideExtension;
651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    assert (sideExtension == null) == (tail == null);
661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  private Optional<BstInOrderPath<N>> computeNextInOrder(BstSide side) {
691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    if (getTip().hasChild(side)) {
701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      BstInOrderPath<N> path = extension(this, side);
711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      BstSide otherSide = side.other();
721d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      while (path.getTip().hasChild(otherSide)) {
731d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        path = extension(path, otherSide);
741d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
751d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return Optional.of(path);
761d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    } else {
771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      BstInOrderPath<N> current = this;
781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      while (current.sideExtension == side) {
791d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        current = current.getPrefix();
801d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
811d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      current = current.prefixOrNull();
821d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return Optional.fromNullable(current);
831d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
841d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
851d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
861d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  private Optional<BstInOrderPath<N>> nextInOrder(BstSide side) {
871d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    Optional<BstInOrderPath<N>> result;
881d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    switch (side) {
891d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      case LEFT:
901d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        result = prevInOrder;
911d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        return (result == null) ? prevInOrder = computeNextInOrder(side) : result;
921d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      case RIGHT:
931d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        result = nextInOrder;
941d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        return (result == null) ? nextInOrder = computeNextInOrder(side) : result;
951d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      default:
961d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        throw new AssertionError();
971d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
981d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
991d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1001d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
1011d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * Returns {@code true} if there is a next path in an in-order traversal in the given direction.
1021d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
1031d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public boolean hasNext(BstSide side) {
1041d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return nextInOrder(side).isPresent();
1051d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
1061d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1071d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
1081d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * Returns the next path in an in-order traversal in the given direction.
1091d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   *
1101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * @throws NoSuchElementException if this would be the last path in an in-order traversal
1111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
1121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public BstInOrderPath<N> next(BstSide side) {
1131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    if (!hasNext(side)) {
1141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      throw new NoSuchElementException();
1151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
1161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return nextInOrder(side).get();
1171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
1181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
1201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * Returns the direction this path went in relative to its tail path, or {@code null} if this
1211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * path has no tail.
1221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
1231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public BstSide getSideOfExtension() {
1241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return sideExtension;
1251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
1261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert}
127