blob: a24972e094f36e49b068da86131f1a616d525d2f [file] [log] [blame]
// Copyright 2007 The Closure Library Authors. All Rights Reserved.
//
// 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.
goog.provide('goog.structs.AvlTreeTest');
goog.setTestOnly('goog.structs.AvlTreeTest');
goog.require('goog.array');
goog.require('goog.structs.AvlTree');
goog.require('goog.testing.jsunit');
/**
* This test verifies that we can insert strings into the AvlTree and have
* them be stored and sorted correctly by the default comparator.
*/
function testInsertsWithDefaultComparator() {
var tree = new goog.structs.AvlTree();
var values = ['bill', 'blake', 'elliot', 'jacob', 'john', 'myles', 'ted'];
// Insert strings into tree out of order
tree.add(values[4]);
tree.add(values[3]);
tree.add(values[0]);
tree.add(values[6]);
tree.add(values[5]);
tree.add(values[1]);
tree.add(values[2]);
// Verify strings are stored in sorted order
var i = 0;
tree.inOrderTraverse(function(value) {
assertEquals(values[i], value);
i += 1;
});
assertEquals(i, values.length);
// Verify that no nodes are visited if the start value is larger than all
// values
tree.inOrderTraverse(function(value) {
fail();
}, 'zed');
// Verify strings are stored in sorted order
i = values.length;
tree.reverseOrderTraverse(function(value) {
i--;
assertEquals(values[i], value);
});
assertEquals(i, 0);
// Verify that no nodes are visited if the start value is smaller than all
// values
tree.reverseOrderTraverse(function(value) {
fail();
}, 'aardvark');
}
/**
* This test verifies that we can insert strings into and remove strings from
* the AvlTree and have the only the non-removed values be stored and sorted
* correctly by the default comparator.
*/
function testRemovesWithDefaultComparator() {
var tree = new goog.structs.AvlTree();
var values = ['bill', 'blake', 'elliot', 'jacob', 'john', 'myles', 'ted'];
// Insert strings into tree out of order
tree.add('frodo');
tree.add(values[4]);
tree.add(values[3]);
tree.add(values[0]);
tree.add(values[6]);
tree.add('samwise');
tree.add(values[5]);
tree.add(values[1]);
tree.add(values[2]);
tree.add('pippin');
// Remove strings from tree
assertEquals(tree.remove('samwise'), 'samwise');
assertEquals(tree.remove('pippin'), 'pippin');
assertEquals(tree.remove('frodo'), 'frodo');
assertEquals(tree.remove('merry'), null);
// Verify strings are stored in sorted order
var i = 0;
tree.inOrderTraverse(function(value) {
assertEquals(values[i], value);
i += 1;
});
assertEquals(i, values.length);
}
/**
* This test verifies that we can insert values into and remove values from
* the AvlTree and have them be stored and sorted correctly by a custom
* comparator.
*/
function testInsertsAndRemovesWithCustomComparator() {
var tree = new goog.structs.AvlTree(function(a, b) {
return a - b;
});
var NUM_TO_INSERT = 37;
var valuesToRemove = [1, 0, 6, 7, 36];
// Insert ints into tree out of order
var values = [];
for (var i = 0; i < NUM_TO_INSERT; i += 1) {
tree.add(i);
values.push(i);
}
for (var i = 0; i < valuesToRemove.length; i += 1) {
assertEquals(tree.remove(valuesToRemove[i]), valuesToRemove[i]);
goog.array.remove(values, valuesToRemove[i]);
}
assertEquals(tree.remove(-1), null);
assertEquals(tree.remove(37), null);
// Verify strings are stored in sorted order
var i = 0;
tree.inOrderTraverse(function(value) {
assertEquals(values[i], value);
i += 1;
});
assertEquals(i, values.length);
}
/**
* This test verifies that we can insert values into and remove values from
* the AvlTree and have it maintain the AVL-Tree upperbound on its height.
*/
function testAvlTreeHeight() {
var tree = new goog.structs.AvlTree(function(a, b) {
return a - b;
});
var NUM_TO_INSERT = 2000;
var NUM_TO_REMOVE = 500;
// Insert ints into tree out of order
for (var i = 0; i < NUM_TO_INSERT; i += 1) {
tree.add(i);
}
// Remove valuse
for (var i = 0; i < NUM_TO_REMOVE; i += 1) {
tree.remove(i);
}
assertTrue(tree.getHeight() <= 1.4405 *
(Math.log(NUM_TO_INSERT - NUM_TO_REMOVE + 2) / Math.log(2)) - 1.3277);
}
/**
* This test verifies that we can insert values into and remove values from
* the AvlTree and have its contains method correctly determine the values it
* is contains.
*/
function testAvlTreeContains() {
var tree = new goog.structs.AvlTree();
var values = ['bill', 'blake', 'elliot', 'jacob', 'john', 'myles', 'ted'];
// Insert strings into tree out of order
tree.add('frodo');
tree.add(values[4]);
tree.add(values[3]);
tree.add(values[0]);
tree.add(values[6]);
tree.add('samwise');
tree.add(values[5]);
tree.add(values[1]);
tree.add(values[2]);
tree.add('pippin');
// Remove strings from tree
assertEquals(tree.remove('samwise'), 'samwise');
assertEquals(tree.remove('pippin'), 'pippin');
assertEquals(tree.remove('frodo'), 'frodo');
for (var i = 0; i < values.length; i += 1) {
assertTrue(tree.contains(values[i]));
}
assertFalse(tree.contains('samwise'));
assertFalse(tree.contains('pippin'));
assertFalse(tree.contains('frodo'));
}
/**
* This test verifies that we can insert values into and remove values from
* the AvlTree and have its indexOf method correctly determine the in-order
* index of the values it contains.
*/
function testAvlTreeIndexOf() {
var tree = new goog.structs.AvlTree();
var values = ['bill', 'blake', 'elliot', 'jacob', 'john', 'myles', 'ted'];
// Insert strings into tree out of order
tree.add('frodo');
tree.add(values[4]);
tree.add(values[3]);
tree.add(values[0]);
tree.add(values[6]);
tree.add('samwise');
tree.add(values[5]);
tree.add(values[1]);
tree.add(values[2]);
tree.add('pippin');
// Remove strings from tree
assertEquals('samwise', tree.remove('samwise'));
assertEquals('pippin', tree.remove('pippin'));
assertEquals('frodo', tree.remove('frodo'));
for (var i = 0; i < values.length; i += 1) {
assertEquals(i, tree.indexOf(values[i]));
}
assertEquals(-1, tree.indexOf('samwise'));
assertEquals(-1, tree.indexOf('pippin'));
assertEquals(-1, tree.indexOf('frodo'));
}
/**
* This test verifies that we can insert values into and remove values from
* the AvlTree and have its minValue and maxValue routines return the correct
* min and max values contained by the tree.
*/
function testMinAndMaxValues() {
var tree = new goog.structs.AvlTree(function(a, b) {
return a - b;
});
var NUM_TO_INSERT = 2000;
var NUM_TO_REMOVE = 500;
// Insert ints into tree out of order
for (var i = 0; i < NUM_TO_INSERT; i += 1) {
tree.add(i);
}
// Remove valuse
for (var i = 0; i < NUM_TO_REMOVE; i += 1) {
tree.remove(i);
}
assertEquals(tree.getMinimum(), NUM_TO_REMOVE);
assertEquals(tree.getMaximum(), NUM_TO_INSERT - 1);
}
/**
* This test verifies that we can insert values into and remove values from
* the AvlTree and traverse the tree in reverse order using the
* reverseOrderTraverse routine.
*/
function testReverseOrderTraverse() {
var tree = new goog.structs.AvlTree(function(a, b) {
return a - b;
});
var NUM_TO_INSERT = 2000;
var NUM_TO_REMOVE = 500;
// Insert ints into tree out of order
for (var i = 0; i < NUM_TO_INSERT; i += 1) {
tree.add(i);
}
// Remove valuse
for (var i = 0; i < NUM_TO_REMOVE; i += 1) {
tree.remove(i);
}
var i = NUM_TO_INSERT - 1;
tree.reverseOrderTraverse(function(value) {
assertEquals(value, i);
i -= 1;
});
assertEquals(i, NUM_TO_REMOVE - 1);
}
/**
* Verifies correct behavior of getCount(). See http://b/4347755
*/
function testGetCountBehavior() {
var tree = new goog.structs.AvlTree();
tree.add(1);
tree.remove(1);
assertEquals(0, tree.getCount());
var values = ['bill', 'blake', 'elliot', 'jacob', 'john', 'myles', 'ted'];
// Insert strings into tree out of order
tree.add('frodo');
tree.add(values[4]);
tree.add(values[3]);
tree.add(values[0]);
tree.add(values[6]);
tree.add('samwise');
tree.add(values[5]);
tree.add(values[1]);
tree.add(values[2]);
tree.add('pippin');
assertEquals(10, tree.getCount());
assertEquals(
tree.root_.left.count + tree.root_.right.count + 1, tree.getCount());
// Remove strings from tree
assertEquals('samwise', tree.remove('samwise'));
assertEquals('pippin', tree.remove('pippin'));
assertEquals('frodo', tree.remove('frodo'));
assertEquals(null, tree.remove('merry'));
assertEquals(7, tree.getCount());
assertEquals(
tree.root_.left.count + tree.root_.right.count + 1, tree.getCount());
}
/**
* This test verifies that getKthOrder gets the correct value.
*/
function testGetKthOrder() {
var tree = new goog.structs.AvlTree(function(a, b) {
return a - b;
});
var NUM_TO_INSERT = 2000;
var NUM_TO_REMOVE = 500;
// Insert ints into tree out of order
for (var i = 0; i < NUM_TO_INSERT; i += 1) {
tree.add(i);
}
// Remove values.
for (var i = 0; i < NUM_TO_REMOVE; i += 1) {
tree.remove(i);
}
for (var k = 0; k < tree.getCount(); ++k) {
assertEquals(NUM_TO_REMOVE + k, tree.getKthValue(k));
}
}