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 Bringertimport static com.google.common.collect.BstModificationResult.ModificationType.IDENTITY; 191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport static com.google.common.collect.BstModificationResult.ModificationType.REBUILDING_CHANGE; 201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport static com.google.common.collect.BstModificationResult.ModificationType.REBALANCING_CHANGE; 211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport static com.google.common.collect.BstSide.LEFT; 221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport static com.google.common.collect.BstSide.RIGHT; 231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport com.google.common.annotations.GwtCompatible; 251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport com.google.common.collect.BstModificationResult.ModificationType; 261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport javax.annotation.Nullable; 281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert/** 301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * The result of a mutation operation performed at a single location in a binary search tree. 311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * 321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * @author Louis Wasserman 331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * @param <K> The key type of the nodes in the modified binary search tree. 341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * @param <N> The type of the nodes in the modified binary search tree. 351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert */ 361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert@GwtCompatible 371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertfinal class BstMutationResult<K, N extends BstNode<K, N>> { 381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert /** 391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Creates a {@code BstMutationResult}. 401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * 411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * @param targetKey The key targeted for modification. If {@code originalTarget} or {@code 421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * changedTarget} are non-null, their keys must compare as equal to {@code targetKey}. 431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * @param originalRoot The root of the subtree that was modified. 441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * @param changedRoot The root of the subtree, after the modification and any rebalancing. 451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * @param modificationResult The result of the local modification to an entry. 461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert */ 471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public static <K, N extends BstNode<K, N>> BstMutationResult<K, N> mutationResult( 481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Nullable K targetKey, @Nullable N originalRoot, @Nullable N changedRoot, 491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert BstModificationResult<N> modificationResult) { 501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return new BstMutationResult<K, N>(targetKey, originalRoot, changedRoot, modificationResult); 511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert private final K targetKey; 541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Nullable 561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert private N originalRoot; 571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 581d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Nullable 591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert private N changedRoot; 601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert private final BstModificationResult<N> modificationResult; 621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert private BstMutationResult(@Nullable K targetKey, @Nullable N originalRoot, 641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Nullable N changedRoot, BstModificationResult<N> modificationResult) { 651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert this.targetKey = targetKey; 661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert this.originalRoot = originalRoot; 671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert this.changedRoot = changedRoot; 681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert this.modificationResult = checkNotNull(modificationResult); 691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert /** 721d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Returns the key which was the target of this modification. 731d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert */ 741d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public K getTargetKey() { 751d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return targetKey; 761d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert /** 791d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Returns the root of the subtree that was modified. 801d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert */ 811d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Nullable 821d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public N getOriginalRoot() { 831d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return originalRoot; 841d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 851d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 861d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert /** 871d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Returns the root of the subtree, after the modification and any rebalancing was performed. 881d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert */ 891d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Nullable 901d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public N getChangedRoot() { 911d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return changedRoot; 921d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 931d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 941d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert /** 951d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Returns the entry in the original subtree with key {@code targetKey}, if any. This should not 961d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * be treated as a subtree, but only as an entry, and no guarantees are made about its children 971d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * when viewed as a subtree. 981d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert */ 991d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Nullable 1001d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public N getOriginalTarget() { 1011d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return modificationResult.getOriginalTarget(); 1021d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 1031d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 1041d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert /** 1051d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Returns the result of the modification to {@link #getOriginalTarget()}. This should not be 1061d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * treated as a subtree, but only as an entry, and no guarantees are made about its children when 1071d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * viewed as a subtree. 1081d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert */ 1091d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Nullable 1101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public N getChangedTarget() { 1111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return modificationResult.getChangedTarget(); 1121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 1131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 1141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert ModificationType modificationType() { 1151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return modificationResult.getType(); 1161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 1171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 1181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert /** 1191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * If this mutation was to an immediate child subtree of the specified root on the specified 1201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * side, returns the {@code BstMutationResult} of applying the mutation to the appropriate child 1211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * of the specified root and rebalancing using the specified mutation rule. 1221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert */ 1231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public BstMutationResult<K, N> lift(N liftOriginalRoot, BstSide side, 1241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert BstNodeFactory<N> nodeFactory, BstBalancePolicy<N> balancePolicy) { 1251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assert liftOriginalRoot != null & side != null & nodeFactory != null & balancePolicy != null; 1261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert switch (modificationType()) { 1271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert case IDENTITY: 1281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert this.originalRoot = this.changedRoot = liftOriginalRoot; 1291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return this; 1301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert case REBUILDING_CHANGE: 1311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert case REBALANCING_CHANGE: 1321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert this.originalRoot = liftOriginalRoot; 1331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert N resultLeft = liftOriginalRoot.childOrNull(LEFT); 1341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert N resultRight = liftOriginalRoot.childOrNull(RIGHT); 1351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert switch (side) { 1361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert case LEFT: 1371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert resultLeft = changedRoot; 1381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert break; 1391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert case RIGHT: 1401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert resultRight = changedRoot; 1411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert break; 1421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert default: 1431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert throw new AssertionError(); 1441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 1451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert if (modificationType() == REBUILDING_CHANGE) { 1461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert this.changedRoot = nodeFactory.createNode(liftOriginalRoot, resultLeft, resultRight); 1471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } else { 1481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert this.changedRoot = 1491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert balancePolicy.balance(nodeFactory, liftOriginalRoot, resultLeft, resultRight); 1501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 1511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return this; 1521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert default: 1531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert throw new AssertionError(); 1541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 1551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 1561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert} 157