com.google.common.collect.BstInOrderPath Maven / Gradle / Ivy
/*
* 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;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy