com.google.common.collect.BstInOrderPath Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of guava Show documentation
Show all versions of guava Show documentation
Guava is a suite of core and expanded libraries that include
utility classes, google's collections, io classes, and much
much more.
/*
* Copyright (C) 2011 The Guava Authors
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the
* License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied. See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.common.collect;
import static com.google.common.base.Preconditions.checkNotNull;
import com.google.common.annotations.GwtCompatible;
import com.google.common.base.Optional;
import java.util.NoSuchElementException;
import javax.annotation.Nullable;
/**
* A {@code BstPath} supporting inorder traversal operations.
*
* @author Louis Wasserman
*/
@GwtCompatible
final class BstInOrderPath> extends BstPath> {
/**
* The factory to use to construct {@code BstInOrderPath} values.
*/
public static > BstPathFactory> inOrderFactory() {
return new BstPathFactory>() {
@Override
public BstInOrderPath extension(BstInOrderPath path, BstSide side) {
return BstInOrderPath.extension(path, side);
}
@Override
public BstInOrderPath initialPath(N root) {
return new BstInOrderPath(root, null, null);
}
};
}
private static > BstInOrderPath extension(
BstInOrderPath path, BstSide side) {
checkNotNull(path);
N tip = path.getTip();
return new BstInOrderPath(tip.getChild(side), side, path);
}
private final BstSide sideExtension;
private transient Optional> prevInOrder;
private transient Optional> nextInOrder;
private BstInOrderPath(
N tip, @Nullable BstSide sideExtension, @Nullable BstInOrderPath tail) {
super(tip, tail);
this.sideExtension = sideExtension;
assert (sideExtension == null) == (tail == null);
}
private Optional> computeNextInOrder(BstSide side) {
if (getTip().hasChild(side)) {
BstInOrderPath path = extension(this, side);
BstSide otherSide = side.other();
while (path.getTip().hasChild(otherSide)) {
path = extension(path, otherSide);
}
return Optional.of(path);
} else {
BstInOrderPath current = this;
while (current.sideExtension == side) {
current = current.getPrefix();
}
current = current.prefixOrNull();
return Optional.fromNullable(current);
}
}
private Optional> nextInOrder(BstSide side) {
Optional> result;
switch (side) {
case LEFT:
result = prevInOrder;
return (result == null) ? prevInOrder = computeNextInOrder(side) : result;
case RIGHT:
result = nextInOrder;
return (result == null) ? nextInOrder = computeNextInOrder(side) : result;
default:
throw new AssertionError();
}
}
/**
* Returns {@code true} if there is a next path in an in-order traversal in the given direction.
*/
public boolean hasNext(BstSide side) {
return nextInOrder(side).isPresent();
}
/**
* Returns the next path in an in-order traversal in the given direction.
*
* @throws NoSuchElementException if this would be the last path in an in-order traversal
*/
public BstInOrderPath next(BstSide side) {
if (!hasNext(side)) {
throw new NoSuchElementException();
}
return nextInOrder(side).get();
}
/**
* Returns the direction this path went in relative to its tail path, or {@code null} if this
* path has no tail.
*/
public BstSide getSideOfExtension() {
return sideExtension;
}
}