diff --git a/packages/red-black-tree/package.json b/packages/red-black-tree/package.json index da34f5e..6679b34 100644 --- a/packages/red-black-tree/package.json +++ b/packages/red-black-tree/package.json @@ -34,7 +34,7 @@ "ava": "^0.24.0", "rimraf": "^2.6.2", "tslint": "^5.9.1", - "typescript": "^2.6.2" + "typescript": "3.5.1" }, "ava": { "files": [ diff --git a/packages/red-black-tree/src/internals/path.ts b/packages/red-black-tree/src/internals/path.ts index eaa7ad9..5d58b29 100644 --- a/packages/red-black-tree/src/internals/path.ts +++ b/packages/red-black-tree/src/internals/path.ts @@ -67,6 +67,7 @@ export class PathNode { release (): PathNode { var p = this.parent; this.node = NONE; + this.next = BRANCH.NONE; this.parent = PathNode.cache; PathNode.cache = this; return p; diff --git a/packages/red-black-tree/tests/internals/rebalance.ts b/packages/red-black-tree/tests/internals/rebalance.ts new file mode 100644 index 0000000..f741e87 --- /dev/null +++ b/packages/red-black-tree/tests/internals/rebalance.ts @@ -0,0 +1,77 @@ +import test from 'ava'; +import { empty, set } from '../../src'; +import { RedBlackTreeStructure, isNone } from '../../src/internals'; + +let tree: RedBlackTreeStructure; + +type User = { + name: string, + id: string +}; + +const testUser1: User = { + name: 'Luke', + id: '298' +}; + +const testUser2: User = { + name: 'Leia', + id: '299' +}; + +const testUser3: User = { + name: 'Han', + id: '300' +}; + +const testUser4: User = { + name: 'Chewbacca', + id: '301' +}; + +test.beforeEach(() => { + tree = empty((a, b) => a < b ? -1 : (a > b ? 1 : 0), true); +}); + +test('should keep the tree balanced', t => { + t.plan(13); + + // Set 298 and make sure it's the root and no other elements are there + tree = set(testUser1.id, testUser1, tree); + t.is(tree._root.key, testUser1.id); + t.is(isNone(tree._root._left), true); + t.is(isNone(tree._root._right), true); + + // Set 299, no rebalance. 299 should be on the right + tree = set(testUser2.id, testUser2, tree); + t.is(tree._root.key, testUser1.id); + t.is(isNone(tree._root._left), true); + t.is(tree._root._right.key, testUser2.id); + + // Set 300, this should cause a rebalance that puts 299 at the top + tree = set(testUser3.id, testUser3, tree); + t.is(tree._root.key, testUser2.id); // 299 is root + t.is(tree._root._left.key, testUser1.id); // 298 goes left + t.is(tree._root._right.key, testUser3.id); // 300 goes right + + // Set 301, no rebalance - will go on the right of 300 + tree = set(testUser4.id, testUser4, tree); + t.is(tree._root.key, testUser2.id); // 299 is root + t.is(tree._root._left.key, testUser1.id); // 298 goes left + t.is(tree._root._right.key, testUser3.id); // 300 goes right + t.is(tree._root._right._right.key, testUser4.id); // 300 goes right +}); + +test('should keep the tree balanced - many items synchronously', t => { + // Add accounts to the tree which will trigger lots of rebalancing + for (let i = 0; i < 1000; i++) { + const user: User = { + name: i.toString(), + id: i.toString() + }; + tree = set(user.id, user, tree); + } + + t.is(tree._root.key, '487'); + t.is(tree._size, 1000); +});