예제 #1
0
 @SuppressWarnings("unchecked")
 private void forEach(AVLTree t, PSet.Consumer<K> action) {
   if (t.isEmpty()) {
     return;
   }
   action.accept((K) t.key());
   forEach(t.left(), action);
   forEach(t.right(), action);
 }
예제 #2
0
 @Test
 public void no_change() {
   AVLTree<String, String> t0 = AVLTree.create();
   AVLTree<String, String> t1 = t0.put("1", "1");
   assertThat(t1.put("1", "1")).isSameAs(t1);
   assertThat(t1.remove("3")).isSameAs(t1);
   AVLTree<String, String> t2 = t0.put("2", "2");
   assertThat(t2.put("2", "2")).isSameAs(t2);
   assertThat(t2.remove("3")).isSameAs(t2);
 }
예제 #3
0
 private static AVLTree combineTrees(AVLTree l, AVLTree r) {
   if (l.isEmpty()) {
     return r;
   }
   if (r.isEmpty()) {
     return l;
   }
   NodeRef oldNode = new NodeRef();
   AVLTree newRight = removeMinBinding(r, oldNode);
   return balance(l, oldNode.node.key(), oldNode.node.value(), newRight);
 }
예제 #4
0
 @Override
 public int hashCode() {
   if (hashCode == 0) {
     int result = key.hashCode();
     result = result * 31 + left.hashCode();
     result = result * 31 + right.hashCode();
     result = result * 31 + value.hashCode();
     hashCode = result;
   }
   return hashCode;
 }
예제 #5
0
  @Test
  public void test() {
    List<Integer> keys = new ArrayList<>();
    for (int i = 0; i < 100; i++) {
      keys.add(i);
    }
    Collections.shuffle(keys);

    AVLTree<Integer, Object> t = AVLTree.create();
    for (Integer key : keys) {
      t = t.add(key);
      assertThat(t.add(key)).isSameAs(t);
    }
    assertThat(Counter.countSet(t)).isEqualTo(100);
    assertThat(Counter.countMap(t)).isEqualTo(100);
    assertThat(t.height()).isGreaterThanOrEqualTo(8).isLessThanOrEqualTo(10);

    for (Integer key : keys) {
      assertThat(t.contains(key)).isTrue();
      t = t.remove(key);
      assertThat(t.remove(key)).isSameAs(t);
    }
    assertThat(Counter.countSet(t)).isEqualTo(0);
    assertThat(Counter.countMap(t)).isEqualTo(0);
  }
예제 #6
0
  @Test
  public void test_replace_root() {
    AVLTree<String, String> t0 = AVLTree.create();
    AVLTree<String, String> t1 = t0.put("1", "a");
    AVLTree<String, String> t2 = t1.put("1", "b");

    assertThat(t1).isNotSameAs(t2);
    assertThat(t1.get("1")).isEqualTo("a");
    assertThat(t2.get("1")).isEqualTo("b");
  }
예제 #7
0
 private static AVLTree removeMinBinding(AVLTree t, NodeRef noderemoved) {
   assert !t.isEmpty();
   if (t.left().isEmpty()) {
     noderemoved.node = t;
     return t.right();
   }
   return balance(removeMinBinding(t.left(), noderemoved), t.key(), t.value(), t.right());
 }
예제 #8
0
 @Test
 public void test_empty() {
   AVLTree<String, String> t = AVLTree.create();
   assertThat(t).as("singleton").isSameAs(AVLTree.create());
   assertThat(t.get("anything")).isNull();
   assertThat(t.remove("anything")).isSameAs(t);
   assertThat(t.toString()).isEqualTo("");
   assertThat(t.hashCode()).isEqualTo(0);
 }
예제 #9
0
 /**
  * Subtraction must not be used for comparison of keys due to possibility of integer overflow,
  * this for example will be the case for sequence below, which was generated using random number
  * generator.
  */
 @Test
 public void do_not_use_subtraction_for_comparison_of_keys() {
   Key[] keys = {
     new Key(2043979982, ""),
     new Key(-36348207, ""),
     new Key(-1864559204, ""),
     new Key(-2018458363, ""),
     new Key(-152409201, ""),
     new Key(-1786252453, ""),
     new Key(-1853960690, "")
   };
   AVLTree<Object, Object> t = AVLTree.create();
   for (Key key : keys) {
     t = t.add(key);
   }
   for (Key key : keys) {
     assertThat(t.get(key)).as("found").isNotNull();
     assertThat(t.remove(key)).as("removed").isNotSameAs(t);
   }
 }
예제 #10
0
  @Test
  public void balancing_should_preserve_buckets() {
    Object k1 = new Key(1, "k1");
    Object k2 = new Key(2, "k2");
    Object k3 = new Key(3, "k3");
    Object k4 = new Key(4, "k4");
    AVLTree<Object, Object> t = AVLTree.create().put(k1, "v1").put(k2, "v2").put(k3, "v3");

    Object k1_1 = new Key(1, "k1_1");
    t = t.put(k1_1, "v1_1");

    t = t.put(k4, "v4");
    assertThat(t.height()).as("height after balancing").isEqualTo(3);
    assertThat(t.get(k1_1)).isEqualTo("v1_1");
  }
예제 #11
0
 @SuppressWarnings("unchecked")
 @Nullable
 @Override
 public V get(K key) {
   Preconditions.checkNotNull(key);
   AVLTree t = this;
   while (!t.isEmpty()) {
     int c = KEY_COMPARATOR.compare(key, t.key());
     if (c == 0) {
       return (V) t.value();
     } else if (c < 0) {
       t = t.left();
     } else {
       t = t.right();
     }
   }
   return null;
 }
예제 #12
0
 private static AVLTree remove(Object key, AVLTree t) {
   if (t.isEmpty()) {
     return t;
   }
   int result = KEY_COMPARATOR.compare(key, t.key());
   if (result == 0) {
     return combineTrees(t.left(), t.right());
   } else if (result < 0) {
     AVLTree left = remove(key, t.left());
     if (left == t.left()) {
       return t;
     }
     return balance(left, t.key(), t.value(), t.right());
   } else {
     AVLTree right = remove(key, t.right());
     if (right == t.right()) {
       return t;
     }
     return balance(t.left(), t.key(), t.value(), right);
   }
 }
예제 #13
0
 @Override
 public String toString() {
   return " " + key + "->" + value + left.toString() + right.toString();
 }
예제 #14
0
 private static int incrementHeight(AVLTree l, AVLTree r) {
   return (l.height() > r.height() ? l.height() : r.height()) + 1;
 }
예제 #15
0
  @Test
  public void hashCode_and_equals_should_not_depend_on_order_of_construction() {
    Object o1 = new Key(21, "o1");
    Object o2 = new Key(45, "o2");
    AVLTree<Object, Object> t1 = AVLTree.create().add(o1).add(o2);
    AVLTree<Object, Object> t2 = AVLTree.create().add(o2).add(o1);
    assertThat(t1.key()).as("shape is different").isNotEqualTo(t2.key());

    assertThat(t1.hashCode()).isEqualTo(t2.hashCode());
    assertThat(t1).isEqualTo(t2);
    assertThat(t2).isEqualTo(t1);

    Object o3 = new Key(0, "o3");
    AVLTree<Object, Object> t3 = t1.add(o3);
    assertThat(t1.hashCode()).isEqualTo(t3.hashCode());
    assertThat(t1).isNotEqualTo(t3);
    assertThat(t3).isNotEqualTo(t1);
  }
예제 #16
0
 private static AVLTree createNode(AVLTree newLeft, AVLTree oldTree, AVLTree newRight) {
   return createNode(newLeft, oldTree.key(), oldTree.value(), newRight);
 }
예제 #17
0
 private static AVLTree balance(AVLTree l, Object key, Object value, AVLTree r) {
   if (l.height() > r.height() + 2) {
     assert !l.isEmpty();
     AVLTree ll = l.left();
     AVLTree lr = l.right();
     if (ll.height() >= lr.height()) {
       return createNode(ll, l, createNode(lr, key, value, r));
     }
     assert !lr.isEmpty();
     AVLTree lrl = lr.left();
     AVLTree lrr = lr.right();
     return createNode(createNode(ll, l, lrl), lr, createNode(lrr, key, value, r));
   }
   if (r.height() > l.height() + 2) {
     assert !r.isEmpty();
     AVLTree rl = r.left();
     AVLTree rr = r.right();
     if (rr.height() >= rl.height()) {
       return createNode(createNode(l, key, value, rl), r, rr);
     }
     assert !rl.isEmpty();
     AVLTree rll = rl.left();
     AVLTree rlr = rl.right();
     return createNode(createNode(l, key, value, rll), rl, createNode(rlr, r, rr));
   }
   return createNode(l, key, value, r);
 }
예제 #18
0
  @Test
  public void test_one_element() {
    AVLTree<String, String> t0 = AVLTree.create();
    AVLTree<String, String> t1 = t0.put("1", "a");
    AVLTree<String, String> t2 = t0.put("2", "b");

    assertThat(t0).isNotSameAs(t1).isNotSameAs(t2);
    assertThat(t1).isNotSameAs(t2);

    assertThat(t0.get("1")).isNull();
    assertThat(t0.get("2")).isNull();
    assertThat(t0.get("3")).isNull();

    assertThat(t1.get("1")).isEqualTo("a");
    assertThat(t1.get("2")).isNull();
    assertThat(t2.get("3")).isNull();

    assertThat(t2.get("1")).isNull();
    assertThat(t2.get("2")).isEqualTo("b");
    assertThat(t2.get("3")).isNull();
  }
예제 #19
0
  @Test
  public void buckets() {
    Object k1 = new Key(42, "k1");
    Object k2 = new Key(42, "k2");
    Object k3 = new Key(42, "k3");
    AVLTree<Object, Object> t = AVLTree.create().put(k1, "v1").put(k2, "v2");

    assertThat(t.toString()).as("should create bucket").isEqualTo(" k2->v2 k1->v1");

    AVLTree<Object, Object> t2 = AVLTree.create().put(k2, "v2").put(k1, "v1");
    assertThat(t2.toString())
        .as("toString depends on order of operations")
        .isEqualTo(" k1->v1 k2->v2");

    assertThat(t.equals(t2)).as("should compare buckets").isTrue();
    assertThat(t2.equals(t)).as("should compare buckets").isTrue();

    assertThat(t.hashCode())
        .isEqualTo(
            ((31 * k1.hashCode()) ^ "v1".hashCode()) + ((31 * k2.hashCode()) ^ "v2".hashCode()));
    assertThat(t2.hashCode())
        .as("hashCode doesn't depend on order of operations")
        .isEqualTo(t.hashCode());

    assertThat(t.get(k1)).isEqualTo("v1");
    assertThat(t.get(k2)).isEqualTo("v2");
    assertThat(t.get(k3)).as("not such key").isNull();

    assertThat(t.put(k2, "new v2").toString())
        .as("should replace head of bucket")
        .isEqualTo(" k2->new v2 k1->v1");
    assertThat(t.put(k1, "new v1").toString())
        .as("should replace element of bucket")
        .isEqualTo(" k1->new v1 k2->v2");
    assertThat(t.put(k1, "v1")).as("should not change").isSameAs(t);
    assertThat(t.put(k2, "v2")).as("should not change").isSameAs(t);
    assertThat(t.put(k3, "v3").toString())
        .as("should add to bucket")
        .isEqualTo(" k3->v3 k2->v2 k1->v1");

    assertThat(t.remove(k2).toString()).as("should remove head of bucket").isEqualTo(" k1->v1");
    assertThat(t.remove(k1).toString()).as("should remove element of bucket").isEqualTo(" k2->v2");
    assertThat(t.remove(k1).remove(k2).toString()).as("should remove bucket").isEqualTo("");
    assertThat(t.remove(k3)).as("should not change").isSameAs(t);

    HashMap<Object, Object> biConsumer = new HashMap<>();
    t.forEach((k, v) -> assertThat(biConsumer.put(k, v)).as("unique key-value").isNull());
    assertThat(biConsumer).isEqualTo(ImmutableMap.of(k1, "v1", k2, "v2"));

    HashSet<Object> consumer = new HashSet<>();
    t.forEach(k -> assertThat(consumer.add(k)).as("unique key").isTrue());
    assertThat(consumer).containsOnly(k1, k2);
  }
예제 #20
0
 private static AVLTree put(Object key, Object value, AVLTree t) {
   if (t.isEmpty()) {
     return createNode(t, key, value, t);
   }
   int result = KEY_COMPARATOR.compare(key, t.key());
   if (result == 0) {
     if (value.equals(t.value())) {
       return t;
     }
     return createNode(t.left(), key, value, t.right());
   } else if (result < 0) {
     AVLTree left = put(key, value, t.left());
     if (left == t.left()) {
       return t;
     }
     return balance(left, t.key(), t.value(), t.right());
   } else {
     AVLTree right = put(key, value, t.right());
     if (right == t.right()) {
       return t;
     }
     return balance(t.left(), t.key(), t.value(), right);
   }
 }