364 lines
9.5 KiB
JavaScript
364 lines
9.5 KiB
JavaScript
// 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));
|
|
}
|
|
}
|