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.BstOperations.extractMax;
191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport static com.google.common.collect.BstOperations.extractMin;
201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport static com.google.common.collect.BstOperations.insertMax;
211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport static com.google.common.collect.BstOperations.insertMin;
221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport static com.google.common.collect.BstSide.LEFT;
231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport static com.google.common.collect.BstSide.RIGHT;
241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport com.google.common.annotations.GwtCompatible;
261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport javax.annotation.Nullable;
281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert/**
301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * A tree-size-based set of balancing policies, based on <a
311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * href="http://www.swiss.ai.mit.edu/~adams/BB/"> Stephen Adams, "Efficient sets: a balancing
321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * act."</a>.
331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *
341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * @author Louis Wasserman
351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert */
361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert@GwtCompatible
371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertfinal class BstCountBasedBalancePolicies {
381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  private BstCountBasedBalancePolicies() {}
391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  private static final int SINGLE_ROTATE_RATIO = 4;
411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  private static final int SECOND_ROTATE_RATIO = 2;
421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * Returns a balance policy that does no balancing or the bare minimum (for {@code combine}).
451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public static <N extends BstNode<?, N>> BstBalancePolicy<N> noRebalancePolicy(
471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      final BstAggregate<N> countAggregate) {
481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    checkNotNull(countAggregate);
491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return new BstBalancePolicy<N>() {
501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      @Override
511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      public N balance(
521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          BstNodeFactory<N> nodeFactory, N source, @Nullable N left, @Nullable N right) {
531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        return checkNotNull(nodeFactory).createNode(source, left, right);
541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      @Nullable
571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      @Override
581d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      public N combine(BstNodeFactory<N> nodeFactory, @Nullable N left, @Nullable N right) {
591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        if (left == null) {
601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          return right;
611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        } else if (right == null) {
621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          return left;
631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        } else if (countAggregate.treeValue(left) > countAggregate.treeValue(right)) {
641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          return nodeFactory.createNode(
651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert              left, left.childOrNull(LEFT), combine(nodeFactory, left.childOrNull(RIGHT), right));
661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        } else {
671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          return nodeFactory.createNode(right, combine(nodeFactory, left, right.childOrNull(LEFT)),
681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert              right.childOrNull(RIGHT));
691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        }
701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    };
721d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
731d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
741d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
751d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * Returns a balance policy that expects the sizes of each side to be at most one node (added or
761d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * removed) away from being balanced. {@code balance} takes {@code O(1)} time, and {@code
771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * combine} takes {@code O(log n)} time.
781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
791d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public static <K, N extends BstNode<K, N>> BstBalancePolicy<N> singleRebalancePolicy(
801d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      final BstAggregate<N> countAggregate) {
811d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    checkNotNull(countAggregate);
821d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return new BstBalancePolicy<N>() {
831d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      @Override
841d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      public N balance(
851d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          BstNodeFactory<N> nodeFactory, N source, @Nullable N left, @Nullable N right) {
861d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        long countL = countAggregate.treeValue(left);
871d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        long countR = countAggregate.treeValue(right);
881d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        if (countL + countR > 1) {
891d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          if (countR >= SINGLE_ROTATE_RATIO * countL) {
901d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            return rotateL(nodeFactory, source, left, right);
911d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          } else if (countL >= SINGLE_ROTATE_RATIO * countR) {
921d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            return rotateR(nodeFactory, source, left, right);
931d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          }
941d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        }
951d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        return nodeFactory.createNode(source, left, right);
961d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
971d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
981d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      private N rotateL(BstNodeFactory<N> nodeFactory, N source, @Nullable N left, N right) {
991d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        checkNotNull(right);
1001d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        N rl = right.childOrNull(LEFT);
1011d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        N rr = right.childOrNull(RIGHT);
1021d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        if (countAggregate.treeValue(rl) >= SECOND_ROTATE_RATIO * countAggregate.treeValue(rr)) {
1031d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          right = singleR(nodeFactory, right, rl, rr);
1041d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        }
1051d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        return singleL(nodeFactory, source, left, right);
1061d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
1071d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1081d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      private N rotateR(BstNodeFactory<N> nodeFactory, N source, N left, @Nullable N right) {
1091d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        checkNotNull(left);
1101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        N lr = left.childOrNull(RIGHT);
1111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        N ll = left.childOrNull(LEFT);
1121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        if (countAggregate.treeValue(lr) >= SECOND_ROTATE_RATIO * countAggregate.treeValue(ll)) {
1131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          left = singleL(nodeFactory, left, ll, lr);
1141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        }
1151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        return singleR(nodeFactory, source, left, right);
1161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
1171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      private N singleL(BstNodeFactory<N> nodeFactory, N source, @Nullable N left, N right) {
1191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        checkNotNull(right);
1201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        return nodeFactory.createNode(right,
1211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            nodeFactory.createNode(source, left, right.childOrNull(LEFT)),
1221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            right.childOrNull(RIGHT));
1231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
1241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      private N singleR(BstNodeFactory<N> nodeFactory, N source, N left, @Nullable N right) {
1261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        checkNotNull(left);
1271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        return nodeFactory.createNode(left, left.childOrNull(LEFT),
1281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            nodeFactory.createNode(source, left.childOrNull(RIGHT), right));
1291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
1301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      @Nullable
1321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      @Override
1331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      public N combine(BstNodeFactory<N> nodeFactory, @Nullable N left, @Nullable N right) {
1341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        if (left == null) {
1351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          return right;
1361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        } else if (right == null) {
1371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          return left;
1381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        }
1391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        N newRootSource;
1401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        if (countAggregate.treeValue(left) > countAggregate.treeValue(right)) {
1411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          BstMutationResult<K, N> extractLeftMax = extractMax(left, nodeFactory, this);
1421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          newRootSource = extractLeftMax.getOriginalTarget();
1431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          left = extractLeftMax.getChangedRoot();
1441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        } else {
1451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          BstMutationResult<K, N> extractRightMin = extractMin(right, nodeFactory, this);
1461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          newRootSource = extractRightMin.getOriginalTarget();
1471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          right = extractRightMin.getChangedRoot();
1481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        }
1491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        return nodeFactory.createNode(newRootSource, left, right);
1501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
1511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    };
1521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
1531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
1551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * Returns a balance policy that makes no assumptions on the relative balance of the two sides
1561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * and performs a full rebalancing as necessary. Both {@code balance} and {@code combine} take
1571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * {@code O(log n)} time.
1581d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
1591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public static <K, N extends BstNode<K, N>> BstBalancePolicy<N> fullRebalancePolicy(
1601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      final BstAggregate<N> countAggregate) {
1611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    checkNotNull(countAggregate);
1621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    final BstBalancePolicy<N> singleBalancePolicy =
1631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        BstCountBasedBalancePolicies.<K, N>singleRebalancePolicy(countAggregate);
1641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return new BstBalancePolicy<N>() {
1651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      @Override
1661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      public N balance(
1671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          BstNodeFactory<N> nodeFactory, N source, @Nullable N left, @Nullable N right) {
1681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        if (left == null) {
1691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          return insertMin(right, source, nodeFactory, singleBalancePolicy);
1701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        } else if (right == null) {
1711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          return insertMax(left, source, nodeFactory, singleBalancePolicy);
1721d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        }
1731d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        long countL = countAggregate.treeValue(left);
1741d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        long countR = countAggregate.treeValue(right);
1751d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        if (SINGLE_ROTATE_RATIO * countL <= countR) {
1761d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          N resultLeft = balance(nodeFactory, source, left, right.childOrNull(LEFT));
1771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          return singleBalancePolicy.balance(
1781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert              nodeFactory, right, resultLeft, right.childOrNull(RIGHT));
1791d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        } else if (SINGLE_ROTATE_RATIO * countR <= countL) {
1801d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          N resultRight = balance(nodeFactory, source, left.childOrNull(RIGHT), right);
1811d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          return singleBalancePolicy.balance(
1821d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert              nodeFactory, left, left.childOrNull(LEFT), resultRight);
1831d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        } else {
1841d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          return nodeFactory.createNode(source, left, right);
1851d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        }
1861d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
1871d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1881d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      @Nullable
1891d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      @Override
1901d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      public N combine(BstNodeFactory<N> nodeFactory, @Nullable N left, @Nullable N right) {
1911d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        if (left == null) {
1921d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          return right;
1931d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        } else if (right == null) {
1941d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          return left;
1951d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        }
1961d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        long countL = countAggregate.treeValue(left);
1971d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        long countR = countAggregate.treeValue(right);
1981d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        if (SINGLE_ROTATE_RATIO * countL <= countR) {
1991d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          N resultLeft = combine(nodeFactory, left, right.childOrNull(LEFT));
2001d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          return singleBalancePolicy.balance(
2011d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert              nodeFactory, right, resultLeft, right.childOrNull(RIGHT));
2021d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        } else if (SINGLE_ROTATE_RATIO * countR <= countL) {
2031d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          N resultRight = combine(nodeFactory, left.childOrNull(RIGHT), right);
2041d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          return singleBalancePolicy.balance(
2051d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert              nodeFactory, left, left.childOrNull(LEFT), resultRight);
2061d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        } else {
2071d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          return singleBalancePolicy.combine(nodeFactory, left, right);
2081d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        }
2091d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
2101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    };
2111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
2121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert}
213