flo-ll-rb-tree
Version:
A simple left leaning red black tree implementation.
112 lines (89 loc) • 4.24 kB
text/typescript
import { assert, expect } from 'chai';
import { describe } from 'mocha';
import { compareObjs } from './helpers/compare-objs.js';
import { LlRbTree } from '../src/index.js';
import { insert1to7Objs } from './helpers/insert-1-to-7-objs.js';
import { isBlackHeightCorrect, isNoRedEdge } from './helpers/constraints.js';
import { vals1to7Objs } from './helpers/vals-1-to-7-objs.js';
import { countValues } from './helpers/count-values.js';
describe('remove', function() {
it('it should remove items in the tree based on value',
function() {
{
const tree = new LlRbTree(compareObjs);
expect(tree.remove({ val: 112 })).to.not.throw;
insert1to7Objs(tree);
tree.remove({ val: 2 });
expect(tree.toArrayInOrder().map(o => o.val)).to.eql([1,3,3,4,5,6,7]);
tree.remove({ val: 5, name: 'apple pear' });
expect(tree.toArrayInOrder().map(o => o.val)).to.eql([1,3,3,4,6,7]);
expect(tree.remove({ val: 112 })).to.not.throw;
tree.remove({ val: 1, name: 'apple pear' });
tree.remove({ val: 3, name: 'apple pear' });
tree.remove({ val: 3, name: 'apple pear' });
tree.remove({ val: 4, name: 'apple pear' });
tree.remove({ val: 6, name: 'apple pear' });
expect(tree.toArrayInOrder().map(o => o.val)).to.eql([7]);
tree.remove({ val: 7, name: 'apple pear' });
expect(tree.toArrayInOrder().map(o => o.val)).to.eql([]);
tree.insert({ val: 7, name: 'apple pear' });
expect(tree.toArrayInOrder().map(o => o.val)).to.eql([7]);
tree.remove({ val: 7, name: 'pear apple' });
expect(tree.toArrayInOrder().map(o => o.val)).to.eql([]);
expect(tree.root).to.be.undefined;
}
});
it('it should remove multiple items in the tree based if requested',
function() {
const tree = new LlRbTree(compareObjs);
let vals: number[];
insert1to7Objs(tree);
const vals1to7Objs2 = vals1to7Objs.slice();
vals1to7Objs2.splice(1,1);
for (let val of vals1to7Objs2) {
tree.insert(val);
}
tree.insert({ val: 3.5 });
//tree.insertMulti([1,1,2,2,3,3,3,3.5,4,4,5,5,6,6,7,7].map(v => ({ val: v })));
// treeToString(tree, nodeObjToString);
assert(isBlackHeightCorrect(tree), 'tree does not pass \'black height\' constraint');
assert(isNoRedEdge(tree), 'tree does not pass \'no red edge\' constraint')
vals = tree.toArrayInOrder().map(o => o.val);
expect(vals).to.eql([1,1,2,2,3,3,3,3.5,4,4,5,5,6,6,7,7]);
tree.remove({ val: 3 }, true);
// treeToString(tree, nodeObjToString);
vals = tree.toArrayInOrder().map(o => o.val);
expect(vals).to.eql([1,1,2,2,3.5,4,4,5,5,6,6,7,7]);
});
it('it should remove multiple items in the tree based if requested',
function() {
const vals = [1,2,3,3,3,3,3,4,5,6].map(v => ({ val: v, name: v.toString() }));
const tree = new LlRbTree(compareObjs, true, vals);
// const vCount = countValues(tree);
expect(tree.toArrayInOrder().map(o => o.val)).to.eql(
[1,2,3,3,3,3,3,4,5,6]
);
tree.remove({ val: 3, name: 'apple' });
expect(tree.toArrayInOrder().map(o => o.val)).to.eql(
[1,2,3,3,3,3,4,5,6]
);
tree.remove({ val: 3, name: 'pear' });
expect(tree.toArrayInOrder().map(o => o.val)).to.eql(
[1,2,3,3,3,4,5,6]
);
tree.remove(
{ val: 3, name: 'guava' }, false,
(a,b) => (a.val - b.val === 0) && (a.name === b.name)
);
expect(tree.toArrayInOrder().map(o => o.val)).to.eql(
[1,2,3,3,3,4,5,6] // should not have removed
);
tree.remove(
{ val: 3, name: '322' }, false,
(a,b) => (a.val - b.val === 0) && (a.name === b.name)
);
expect(tree.toArrayInOrder().map(o => o.val)).to.eql(
[1,2,3,3,3,4,5,6]
);
});
});