175 lines
4.8 KiB
JavaScript
175 lines
4.8 KiB
JavaScript
defineSuite([
|
|
'Core/Heap'
|
|
], function(
|
|
Heap) {
|
|
'use strict';
|
|
|
|
var length = 100;
|
|
|
|
function checkHeap(heap, comparator) {
|
|
var array = heap.internalArray;
|
|
var pass = true;
|
|
var length = heap.length;
|
|
for (var i = 0; i < length; ++i) {
|
|
var left = 2 * (i + 1) - 1;
|
|
var right = 2 * (i + 1);
|
|
if (left < heap.length) {
|
|
pass = pass && (comparator(array[i], array[left]) <= 0);
|
|
}
|
|
if (right < heap.length) {
|
|
pass = pass && (comparator(array[i], array[right]) <= 0);
|
|
}
|
|
}
|
|
return pass;
|
|
}
|
|
|
|
// min heap
|
|
function comparator(a, b) {
|
|
return a - b;
|
|
}
|
|
|
|
it('maintains heap property on insert', function() {
|
|
var heap = new Heap({
|
|
comparator : comparator
|
|
});
|
|
var pass = true;
|
|
for (var i = 0; i < length; ++i) {
|
|
heap.insert(Math.random());
|
|
pass = pass && checkHeap(heap, comparator);
|
|
}
|
|
|
|
expect(pass).toBe(true);
|
|
});
|
|
|
|
it('maintains heap property on pop', function() {
|
|
var heap = new Heap({
|
|
comparator : comparator
|
|
});
|
|
var i;
|
|
for (i = 0; i < length; ++i) {
|
|
heap.insert(Math.random());
|
|
}
|
|
var pass = true;
|
|
for (i = 0; i < length; ++i) {
|
|
heap.pop();
|
|
pass = pass && checkHeap(heap, comparator);
|
|
}
|
|
expect(pass).toBe(true);
|
|
});
|
|
|
|
it('limited by maximum length', function() {
|
|
var heap = new Heap({
|
|
comparator : comparator
|
|
});
|
|
heap.maximumLength = length / 2;
|
|
var pass = true;
|
|
for (var i = 0; i < length; ++i) {
|
|
heap.insert(Math.random());
|
|
pass = pass && checkHeap(heap, comparator);
|
|
}
|
|
expect(pass).toBe(true);
|
|
expect(heap.length <= heap.maximumLength).toBe(true);
|
|
// allowed one extra slot for swapping
|
|
expect(heap.internalArray.length).toBeLessThanOrEqualTo(heap.maximumLength + 1);
|
|
});
|
|
|
|
it('pops in sorted order', function() {
|
|
var heap = new Heap({
|
|
comparator : comparator
|
|
});
|
|
var i;
|
|
for (i = 0; i < length; ++i) {
|
|
heap.insert(Math.random());
|
|
}
|
|
var curr = heap.pop();
|
|
var pass = true;
|
|
for (i = 0; i < length - 1; ++i) {
|
|
var next = heap.pop();
|
|
pass = pass && (comparator(curr, next) <= 0);
|
|
curr = next;
|
|
}
|
|
expect(pass).toBe(true);
|
|
});
|
|
|
|
it('insert returns the removed element when maximumLength is set', function() {
|
|
var heap = new Heap({
|
|
comparator : comparator
|
|
});
|
|
heap.maximumLength = length;
|
|
|
|
var i;
|
|
var max = 0.0;
|
|
var min = 1.0;
|
|
var values = new Array(length);
|
|
for (i = 0; i < length; ++i) {
|
|
var value = Math.random();
|
|
max = Math.max(max, value);
|
|
min = Math.min(min, value);
|
|
values[i] = value;
|
|
}
|
|
|
|
// Push 99 values
|
|
for (i = 0; i < length - 1; ++i) {
|
|
heap.insert(values[i]);
|
|
}
|
|
|
|
// Push 100th, nothing is removed so it returns undefined
|
|
var removed = heap.insert(values[length - 1]);
|
|
expect(removed).toBeUndefined();
|
|
|
|
// Insert value, an element is removed
|
|
removed = heap.insert(max - 0.1);
|
|
expect(removed).toBeDefined();
|
|
|
|
// If this value is the least priority it will be returned
|
|
removed = heap.insert(max + 0.1);
|
|
expect(removed).toBe(max + 0.1);
|
|
});
|
|
|
|
it('resort', function() {
|
|
function comparator(a, b) {
|
|
return a.distance - b.distance;
|
|
}
|
|
|
|
var i;
|
|
var heap = new Heap({
|
|
comparator : comparator
|
|
});
|
|
for (i = 0; i < length; ++i) {
|
|
heap.insert({
|
|
distance : i / (length - 1),
|
|
id : i
|
|
});
|
|
}
|
|
|
|
// Check that elements are initially sorted
|
|
var element;
|
|
var elements = [];
|
|
var currentId = 0;
|
|
while (heap.length > 0) {
|
|
element = heap.pop();
|
|
elements.push(element);
|
|
expect(element.id).toBeGreaterThanOrEqualTo(currentId);
|
|
currentId = element.id;
|
|
}
|
|
|
|
// Add back into heap
|
|
for (i = 0; i < length; ++i) {
|
|
heap.insert(elements[i]);
|
|
}
|
|
|
|
// Invert priority
|
|
for (i = 0; i < length; ++i) {
|
|
elements[i].distance = 1.0 - elements[i].distance;
|
|
}
|
|
|
|
// Resort and check the the elements are popped in the opposite order now
|
|
heap.resort();
|
|
while (heap.length > 0) {
|
|
element = heap.pop();
|
|
expect(element.id).toBeLessThanOrEqualTo(currentId);
|
|
currentId = element.id;
|
|
}
|
|
});
|
|
});
|