diff --git a/src/data-structures/binary-tree/binary-tree.ts b/src/data-structures/binary-tree/binary-tree.ts index b6f1fd8..8047b2e 100644 --- a/src/data-structures/binary-tree/binary-tree.ts +++ b/src/data-structures/binary-tree/binary-tree.ts @@ -1484,5 +1484,63 @@ export class BinaryTree = BinaryTreeNode this._root = v; } + print(beginRoot: N | null | undefined = this.root) { + const display = (root: N | null | undefined): void => { + const [lines, , ,] = _displayAux(root); + for (const line of lines) { + console.log(line); + } + }; + + const _displayAux = (node: N | null | undefined): [string[], number, number, number] => { + if (node === undefined || node === null) { + return [[], 0, 0, 0]; + } + + if (node && node.right === undefined && node.left === undefined) { + const line = `${node.key}`; + const width = line.length; + const height = 1; + const middle = Math.floor(width / 2); + return [[line], width, height, middle]; + } + + if (node && node.right === undefined) { + const [lines, n, p, x] = _displayAux(node.left); + const s = `${node.key}`; + const u = s.length; + const first_line = ' '.repeat(x + 1) + '_'.repeat(n - x - 1) + s; + const second_line = ' '.repeat(x) + '/' + ' '.repeat(n - x - 1 + u); + const shifted_lines = lines.map(line => line + ' '.repeat(u)); + return [[first_line, second_line, ...shifted_lines], n + u, p + 2, n + Math.floor(u / 2)]; + } + + if (node && node.left === undefined) { + const [lines, n, p, u] = _displayAux(node.right); + const s = `${node.key}`; + const x = s.length; + const first_line = s + '_'.repeat(x) + ' '.repeat(n - x); + const second_line = ' '.repeat(u + x) + '\\' + ' '.repeat(n - x - 1); + const shifted_lines = lines.map(line => ' '.repeat(u) + line); + return [[first_line, second_line, ...shifted_lines], n + x, p + 2, Math.floor(u / 2)]; + } + + const [left, n, p, x] = _displayAux(node.left); + const [right, m, q, y] = _displayAux(node.right); + const s = `${node.key}`; + const u = s.length; + const first_line = ' '.repeat(x + 1) + '_'.repeat(n - x - 1) + s + '_'.repeat(y) + ' '.repeat(m - y); + const second_line = ' '.repeat(x) + '/' + ' '.repeat(n - x - 1 + u + y) + '\\' + ' '.repeat(m - y - 1); + if (p < q) { + left.push(...new Array(q - p).fill(' '.repeat(n))); + } else if (q < p) { + right.push(...new Array(p - q).fill(' '.repeat(m))); + } + const zipped_lines = left.map((a, i) => a + ' '.repeat(u) + right[i]); + return [[first_line, second_line, ...zipped_lines], n + m + u, Math.max(p, q) + 2, n + Math.floor(u / 2)]; + }; + + display(beginRoot); + } // --- end additional methods --- } diff --git a/src/data-structures/binary-tree/bst.ts b/src/data-structures/binary-tree/bst.ts index d626560..7fb27ab 100644 --- a/src/data-structures/binary-tree/bst.ts +++ b/src/data-structures/binary-tree/bst.ts @@ -119,8 +119,8 @@ export class BST = BSTNode> } if (keyOrNode === null) return undefined; // TODO support node as a parameter - let inserted:N | undefined = undefined; - let newNode:N | undefined = undefined; + let inserted:N | undefined; + let newNode:N | undefined; if (keyOrNode instanceof BSTNode) { newNode = keyOrNode; } else if (typeof keyOrNode === 'number') { @@ -129,7 +129,7 @@ export class BST = BSTNode> newNode = undefined; } if (this.root === undefined) { - this._root = newNode; + this._setRoot(newNode); this._size = this.size + 1; inserted = this.root; } else { @@ -538,6 +538,13 @@ export class BST = BSTNode> protected _comparator: BSTComparator = (a, b) => a - b; + protected _setRoot(v: N | undefined) { + if (v) { + v.parent = undefined; + } + this._root = v; + } + /** * The function compares two values using a comparator function and returns whether the first value * is greater than, less than, or equal to the second value. diff --git a/src/data-structures/binary-tree/rb-tree.ts b/src/data-structures/binary-tree/rb-tree.ts index 0d2eda0..e5512d2 100644 --- a/src/data-structures/binary-tree/rb-tree.ts +++ b/src/data-structures/binary-tree/rb-tree.ts @@ -56,7 +56,7 @@ export class RedBlackTree = RBTreeNode(0) as unknown as N; + NIL: N = new RBTreeNode(NaN) as unknown as N; override add(keyOrNode: BTNKey | N | null | undefined, value?: V): N | undefined { let node: N; @@ -89,7 +89,7 @@ export class RedBlackTree = RBTreeNode = RBTreeNode { - // if (this.isRealNode(node)) { - // if (key === node.key) { - // return node; - // } - // - // if (key < node.key) return dfs(node.left!); - // return dfs(node.right!); - // } else { - // return undefined; - // } - // }; - // return dfs(beginRoot); - // } - getNode>( identifier: BTNKey, callback?: C, @@ -317,68 +291,16 @@ export class RedBlackTree = RBTreeNode { - const [lines, , ,] = _displayAux(root); - for (const line of lines) { - console.log(line); - } - }; - - const _displayAux = (node: N | undefined): [string[], number, number, number] => { - if (node === undefined) { - return [[], 0, 0, 0]; - } - - if (node.right === undefined && node.left === undefined) { - const line = `${node.key}`; - const width = line.length; - const height = 1; - const middle = Math.floor(width / 2); - return [[line], width, height, middle]; - } - - if (node.right === undefined) { - const [lines, n, p, x] = _displayAux(node.left); - const s = `${node.key}`; - const u = s.length; - const first_line = ' '.repeat(x + 1) + '_'.repeat(n - x - 1) + s; - const second_line = ' '.repeat(x) + '/' + ' '.repeat(n - x - 1 + u); - const shifted_lines = lines.map(line => line + ' '.repeat(u)); - return [[first_line, second_line, ...shifted_lines], n + u, p + 2, n + Math.floor(u / 2)]; - } - - if (node.left === undefined) { - const [lines, n, p, u] = _displayAux(node.right); - const s = `${node.key}`; - const x = s.length; - const first_line = s + '_'.repeat(x) + ' '.repeat(n - x); - const second_line = ' '.repeat(u + x) + '\\' + ' '.repeat(n - x - 1); - const shifted_lines = lines.map(line => ' '.repeat(u) + line); - return [[first_line, second_line, ...shifted_lines], n + x, p + 2, Math.floor(u / 2)]; - } - - const [left, n, p, x] = _displayAux(node.left); - const [right, m, q, y] = _displayAux(node.right); - const s = `${node.key}`; - const u = s.length; - const first_line = ' '.repeat(x + 1) + '_'.repeat(n - x - 1) + s + '_'.repeat(y) + ' '.repeat(m - y); - const second_line = ' '.repeat(x) + '/' + ' '.repeat(n - x - 1 + u + y) + '\\' + ' '.repeat(m - y - 1); - if (p < q) { - left.push(...new Array(q - p).fill(' '.repeat(n))); - } else if (q < p) { - right.push(...new Array(p - q).fill(' '.repeat(m))); - } - const zipped_lines = left.map((a, i) => a + ' '.repeat(u) + right[i]); - return [[first_line, second_line, ...zipped_lines], n + m + u, Math.max(p, q) + 2, n + Math.floor(u / 2)]; - }; - - display(beginRoot); + protected override _setRoot(v: N) { + if (v) { + v.parent = undefined; + } + this._root = v; } /** @@ -394,7 +316,7 @@ export class RedBlackTree = RBTreeNode = RBTreeNode = RBTreeNode { const node = tree.getNode(20); tree.add(25); // Verify that rotation has occurred - expect(node?.left?.key).toBe(0); + expect(node?.left?.key).toBeNaN(); expect(node?.right?.key).toBe(25); }); @@ -425,18 +425,22 @@ describe('RedBlackTree', () => { tree.add(110); isDebug && tree.print(); + // console.log(tree.dfs()) + // console.log(tree.isBST()) + }); it('should fix the tree after insertion and deletion', () => { - for (let i = 0; i < 100000; i++) { + for (let i = 0; i < 1000; i++) { tree.add(getRandomInt(-100, 1000)); } - for (let i = 0; i < 100000; i++) { + for (let i = 0; i < 1000; i++) { tree.delete(getRandomInt(-100, 1000)); } - for (let i = 0; i < 100000; i++) { + for (let i = 0; i < 1000; i++) { tree.add(getRandomInt(-100, 1000)); tree.delete(getRandomInt(-100, 1000)); } + // console.log(tree.dfs( n => n.key, "in", tree.root, IterationType.RECURSIVE)) }); });