From 9ace3955649af3fe853ef8d12317106a08086e14 Mon Sep 17 00:00:00 2001 From: Revone Date: Thu, 31 Oct 2024 16:18:51 +1300 Subject: [PATCH] fix: Fix bug in BinaryTree.print to support undefined, null, and NIL. Fix #106 --- .../binary-tree/binary-tree.ts | 18 +++++----- src/data-structures/binary-tree/bst.ts | 34 +++++++++---------- .../binary-tree/avl-tree.test.ts | 20 +++++++++++ .../binary-tree/binary-tree.test.ts | 21 ++++++++++++ .../data-structures/binary-tree/bst.test.ts | 17 ++++++---- 5 files changed, 76 insertions(+), 34 deletions(-) diff --git a/src/data-structures/binary-tree/binary-tree.ts b/src/data-structures/binary-tree/binary-tree.ts index 6dafe4f..ee78907 100644 --- a/src/data-structures/binary-tree/binary-tree.ts +++ b/src/data-structures/binary-tree/binary-tree.ts @@ -1681,20 +1681,14 @@ export class BinaryTree< beginRoot: BTNKeyOrNodeOrEntry | R = this._root, options?: BinaryTreePrintOptions ): string { - const opts = { isShowUndefined: false, isShowNull: false, isShowRedBlackNIL: false, ...options }; + const opts = { isShowUndefined: false, isShowNull: true, isShowRedBlackNIL: false, ...options }; beginRoot = this.ensureNode(beginRoot); let output = ''; if (!beginRoot) return output; - if (opts.isShowUndefined) - output += `U for undefined - `; - if (opts.isShowNull) - output += `N for null - `; - if (opts.isShowRedBlackNIL) - output += `S for Sentinel Node(NIL) - `; + if (opts.isShowUndefined) output += `U for undefined\n`; + if (opts.isShowNull) output += `N for null\n`; + if (opts.isShowRedBlackNIL) output += `S for Sentinel Node(NIL)\n`; const display = (root: OptBTNOrNull): void => { const [lines, , ,] = this._displayAux(root, opts); @@ -1709,6 +1703,10 @@ export class BinaryTree< return output; } + override print(options?: BinaryTreePrintOptions, beginRoot: BTNKeyOrNodeOrEntry | R = this._root) { + console.log(this.toVisual(beginRoot, options)); + } + protected _dfs>( callback?: C, pattern?: DFSOrderPattern, diff --git a/src/data-structures/binary-tree/bst.ts b/src/data-structures/binary-tree/bst.ts index d3d00ab..9626c75 100644 --- a/src/data-structures/binary-tree/bst.ts +++ b/src/data-structures/binary-tree/bst.ts @@ -310,28 +310,26 @@ export class BST< if (!isBalanceAdd) { for (const kve of keysOrNodesOrEntriesOrRaws) { const value = valuesIterator?.next().value; - const nn = this.add(kve, value); - inserted.push(nn); + inserted.push(this.add(kve, value)); } return inserted; } - const realBTNExemplars: (R | BTNPureKeyOrNodeOrEntry)[] = []; - - const isRealBTNExemplar = ( - kve: BTNKeyOrNodeOrEntry | R - ): kve is BTNPureKeyOrNodeOrEntry => { - if (kve === undefined || kve === null) return false; - return !(this.isEntry(kve) && (kve[0] === undefined || kve[0] === null)); - }; + const realBTNExemplars: { + key: R | BTNKeyOrNodeOrEntry; + value: V | undefined; + orgIndex: number; + }[] = []; + let i = 0; for (const kve of keysOrNodesOrEntriesOrRaws) { - if (isRealBTNExemplar(kve)) realBTNExemplars.push(kve); + realBTNExemplars.push({ key: kve, value: valuesIterator?.next().value, orgIndex: i }); + i++; } - let sorted: (R | BTNPureKeyOrNodeOrEntry)[] = []; + let sorted: { key: R | BTNKeyOrNodeOrEntry; value: V | undefined; orgIndex: number }[] = []; - sorted = realBTNExemplars.sort((a, b) => { + sorted = realBTNExemplars.sort(({ key: a }, { key: b }) => { let keyA: K | undefined | null, keyB: K | undefined | null; if (this.isEntry(a)) keyA = a[0]; else if (this.isRealNode(a)) keyA = a.key; @@ -355,12 +353,12 @@ export class BST< return 0; }); - const _dfs = (arr: (R | BTNPureKeyOrNodeOrEntry)[]) => { + const _dfs = (arr: { key: R | BTNKeyOrNodeOrEntry; value: V | undefined; orgIndex: number }[]) => { if (arr.length === 0) return; const mid = Math.floor((arr.length - 1) / 2); - const newNode = this.add(arr[mid]); - inserted.push(newNode); + const { key, value, orgIndex } = arr[mid]; + inserted[orgIndex] = this.add(key, value); _dfs(arr.slice(0, mid)); _dfs(arr.slice(mid + 1)); }; @@ -374,8 +372,8 @@ export class BST< const [l, r] = popped; if (l <= r) { const m = l + Math.floor((r - l) / 2); - const newNode = this.add(sorted[m]); - inserted.push(newNode); + const { key, value, orgIndex } = sorted[m]; + inserted[orgIndex] = this.add(key, value); stack.push([m + 1, r]); stack.push([l, m - 1]); } diff --git a/test/unit/data-structures/binary-tree/avl-tree.test.ts b/test/unit/data-structures/binary-tree/avl-tree.test.ts index 8d230f6..b262ce5 100644 --- a/test/unit/data-structures/binary-tree/avl-tree.test.ts +++ b/test/unit/data-structures/binary-tree/avl-tree.test.ts @@ -292,6 +292,26 @@ describe('AVLTree', () => { // You can add more specific assertions to check the tree's balance and structure. }); + it('should addMany undefined and null', () => { + const avl = new AVLTree(); + const addManyWithUndefined = avl.addMany([1, undefined, 3]); + expect(addManyWithUndefined).toEqual([true, false, true]); + expect(avl.get(undefined)).toBe(undefined); + const addManyWithNull = avl.addMany([1, null, 3, 4]); + expect(addManyWithNull).toEqual([true, false, true, true]); + const addManyEntriesWithNull = avl.addMany([ + [1, '1'], + [null, 'null'], + [3, '3'], + [4, '4'] + ]); + expect(addManyEntriesWithNull).toEqual([true, false, true, true]); + expect(avl.get(null)).toBe(undefined); + const node0 = avl.add(0, '0'); + expect(node0).toBe(true); + expect(avl.get(0)).toBe('0'); + }); + it('should balance the tree using _balanceLR when nodes are deleted', () => { const avlTree = new AVLTree(); avlTree.add([10, 'A']); diff --git a/test/unit/data-structures/binary-tree/binary-tree.test.ts b/test/unit/data-structures/binary-tree/binary-tree.test.ts index 4a76625..067d781 100644 --- a/test/unit/data-structures/binary-tree/binary-tree.test.ts +++ b/test/unit/data-structures/binary-tree/binary-tree.test.ts @@ -105,6 +105,27 @@ describe('BinaryTree addMany', () => { expect(tree.getNodeByKey(4)?.value).toBe(44); expect(tree.getNodeByKey(1)?.value).toBe(1); }); + + it('should addMany undefined and null', () => { + const binaryTree = new BinaryTree(); + const addManyWithUndefined = binaryTree.addMany([1, undefined, 3]); + expect(addManyWithUndefined).toEqual([true, false, true]); + expect(binaryTree.get(undefined)).toBe(undefined); + const addManyWithNull = binaryTree.addMany([1, null, 3, 4]); + expect(addManyWithNull).toEqual([true, true, true, true]); + const addManyEntriesWithNull = binaryTree.addMany([ + [1, '1'], + [null, 'null'], + [3, '3'], + [4, '4'] + ]); + expect(addManyEntriesWithNull).toEqual([true, true, true, true]); + expect(binaryTree.get(null)).toBe(undefined); + expect(binaryTree.getNode(null)).toBe(null); + const node0 = binaryTree.add(0, '0'); + expect(node0).toBe(true); + expect(binaryTree.get(0)).toBe('0'); + }); }); describe('BinaryTree', () => { diff --git a/test/unit/data-structures/binary-tree/bst.test.ts b/test/unit/data-structures/binary-tree/bst.test.ts index 4c42d09..6637822 100644 --- a/test/unit/data-structures/binary-tree/bst.test.ts +++ b/test/unit/data-structures/binary-tree/bst.test.ts @@ -16,22 +16,27 @@ describe('BST operations test', () => { expect(isAdd0).toBe(true); expect(bst.get(0)).toBe('0'); }); + it('should addMany undefined and null', () => { const bst = new BST(); const addManyWithUndefined = bst.addMany([1, undefined, 3]); - // TODO - // expect(addManyWithUndefined).toEqual([true, false, true]); - expect(addManyWithUndefined).toEqual([true, true]); + expect(addManyWithUndefined).toEqual([true, false, true]); expect(bst.get(undefined)).toBe(undefined); const addManyWithNull = bst.addMany([1, null, 3, 4]); - // TODO - // expect(addManyWithNull).toEqual([false, false, false, true]); - expect(addManyWithNull).toEqual([true, true, true]); + expect(addManyWithNull).toEqual([true, false, true, true]); + const addManyEntriesWithNull = bst.addMany([ + [1, '1'], + [null, 'null'], + [3, '3'], + [4, '4'] + ]); + expect(addManyEntriesWithNull).toEqual([true, false, true, true]); expect(bst.get(null)).toBe(undefined); const node0 = bst.add(0, '0'); expect(node0).toBe(true); expect(bst.get(0)).toBe('0'); }); + it('should perform various operations on a Binary Search Tree with numeric values', () => { const bst = new BST(); expect(bst).toBeInstanceOf(BST);