From 365bce8f3453b15c54d7dda72f0f998b27c51cb1 Mon Sep 17 00:00:00 2001 From: Eyas Ranjous Date: Thu, 8 Dec 2022 06:37:32 -0300 Subject: [PATCH 1/7] allow aborting traversal --- src/binarySearchTree.d.ts | 6 +++--- src/binarySearchTree.js | 13 +++++++++---- test/binarySearchTree.test.js | 30 ++++++++++++++++++++++++++++++ 3 files changed, 42 insertions(+), 7 deletions(-) diff --git a/src/binarySearchTree.d.ts b/src/binarySearchTree.d.ts index b03bc42..548a003 100644 --- a/src/binarySearchTree.d.ts +++ b/src/binarySearchTree.d.ts @@ -14,8 +14,8 @@ export class BinarySearchTree { root(): BinarySearchTreeNode | null; count(): number; remove(value: T): boolean; - traverseInOrder(cb: (node: BinarySearchTreeNode) => void): void; - traversePreOrder(cb: (node: BinarySearchTreeNode) => void): void; - traversePostOrder(cb: (node: BinarySearchTreeNode) => void): void; + traverseInOrder(cb: (node: BinarySearchTreeNode) => void, abortCb?: () => boolean): void; + traversePreOrder(cb: (node: BinarySearchTreeNode) => void, abortCb?: () => boolean): void; + traversePostOrder(cb: (node: BinarySearchTreeNode) => void, abortCb?: () => boolean): void; clear(): void; } diff --git a/src/binarySearchTree.js b/src/binarySearchTree.js index cf4d5a9..ab65a74 100644 --- a/src/binarySearchTree.js +++ b/src/binarySearchTree.js @@ -289,8 +289,9 @@ class BinarySearchTree { * Traverses the tree in-order (left-node-right) * @public * @param {function} cb + * @param {function} abortCb */ - traverseInOrder(cb) { + traverseInOrder(cb, abortCb) { if (typeof cb !== 'function') { throw new Error('.traverseInOrder expects a callback function'); } @@ -298,6 +299,7 @@ class BinarySearchTree { const traverseRecursive = (current) => { if (current === null) return; traverseRecursive(current.getLeft()); + if (abortCb && abortCb()) return; cb(current); traverseRecursive(current.getRight()); }; @@ -309,14 +311,15 @@ class BinarySearchTree { * Traverses the tree pre-order (node-left-right) * @public * @param {function} cb + * @param {function} abortCb */ - traversePreOrder(cb) { + traversePreOrder(cb, abortCb) { if (typeof cb !== 'function') { throw new Error('.traversePreOrder expects a callback function'); } const traverseRecursive = (current) => { - if (current === null) return; + if (current === null || (abortCb && abortCb())) return; cb(current); traverseRecursive(current.getLeft()); traverseRecursive(current.getRight()); @@ -329,8 +332,9 @@ class BinarySearchTree { * Traverses the tree post-order (left-right-node) * @public * @param {function} cb + * @param {function} abortCb */ - traversePostOrder(cb) { + traversePostOrder(cb, abortCb) { if (typeof cb !== 'function') { throw new Error('.traversePostOrder expects a callback function'); } @@ -339,6 +343,7 @@ class BinarySearchTree { if (current === null) return; traverseRecursive(current.getLeft()); traverseRecursive(current.getRight()); + if (abortCb && abortCb()) return; cb(current); }; diff --git a/test/binarySearchTree.test.js b/test/binarySearchTree.test.js index f15ed77..c663416 100644 --- a/test/binarySearchTree.test.js +++ b/test/binarySearchTree.test.js @@ -123,6 +123,16 @@ describe('BinarySearchTree tests', () => { bst.traverseInOrder((node) => keys.push(node.getValue())); expect(keys).to.deep.equal([20, 30, 40, 50, 60, 80, 90]); }); + + it('traverse in order and allow aborting traversal', () => { + const keys = []; + let counter = 0; + bst.traverseInOrder((node) => { + keys.push(node.getValue()); + counter += 1; + }, () => counter > 2); + expect(keys).to.deep.equal([20, 30, 40]); + }); }); describe('.traversePreOrder(cb)', () => { @@ -131,6 +141,16 @@ describe('BinarySearchTree tests', () => { bst.traversePreOrder((node) => keys.push(node.getValue())); expect(keys).to.deep.equal([50, 30, 20, 40, 80, 60, 90]); }); + + it('traverse pre order and allow aborting traversal', () => { + const keys = []; + let counter = 0; + bst.traversePreOrder((node) => { + keys.push(node.getValue()); + counter += 1; + }, () => counter > 2); + expect(keys).to.deep.equal([50, 30, 20]); + }); }); describe('.traversePostOrder(cb)', () => { @@ -139,6 +159,16 @@ describe('BinarySearchTree tests', () => { bst.traversePostOrder((node) => keys.push(node.getValue())); expect(keys).to.deep.equal([20, 40, 30, 60, 90, 80, 50]); }); + + it('traverse post order and allow aborting traversal', () => { + const keys = []; + let counter = 0; + bst.traversePostOrder((node) => { + keys.push(node.getValue()); + counter += 1; + }, () => counter > 2); + expect(keys).to.deep.equal([20, 40, 30]); + }); }); describe('.remove(value)', () => { From 3cc705a1ab666d51ce509abc2afb3c94bb5e03e5 Mon Sep 17 00:00:00 2001 From: Eyas Ranjous Date: Thu, 8 Dec 2022 06:40:27 -0300 Subject: [PATCH 2/7] extra check --- src/binarySearchTree.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/binarySearchTree.js b/src/binarySearchTree.js index ab65a74..cd5f9ab 100644 --- a/src/binarySearchTree.js +++ b/src/binarySearchTree.js @@ -297,7 +297,7 @@ class BinarySearchTree { } const traverseRecursive = (current) => { - if (current === null) return; + if (current === null || (abortCb && abortCb())) return; traverseRecursive(current.getLeft()); if (abortCb && abortCb()) return; cb(current); @@ -340,7 +340,7 @@ class BinarySearchTree { } const traverseRecursive = (current) => { - if (current === null) return; + if (current === null || (abortCb && abortCb())) return; traverseRecursive(current.getLeft()); traverseRecursive(current.getRight()); if (abortCb && abortCb()) return; From b4e042cda43148ca851bb73c916930d2f972f087 Mon Sep 17 00:00:00 2001 From: Eyas Ranjous Date: Thu, 8 Dec 2022 06:41:38 -0300 Subject: [PATCH 3/7] optional --- src/binarySearchTree.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/binarySearchTree.js b/src/binarySearchTree.js index cd5f9ab..4a4bb4d 100644 --- a/src/binarySearchTree.js +++ b/src/binarySearchTree.js @@ -289,7 +289,7 @@ class BinarySearchTree { * Traverses the tree in-order (left-node-right) * @public * @param {function} cb - * @param {function} abortCb + * @param {function} [abortCb] */ traverseInOrder(cb, abortCb) { if (typeof cb !== 'function') { @@ -311,7 +311,7 @@ class BinarySearchTree { * Traverses the tree pre-order (node-left-right) * @public * @param {function} cb - * @param {function} abortCb + * @param {function} [abortCb] */ traversePreOrder(cb, abortCb) { if (typeof cb !== 'function') { @@ -332,7 +332,7 @@ class BinarySearchTree { * Traverses the tree post-order (left-right-node) * @public * @param {function} cb - * @param {function} abortCb + * @param {function} [abortCb] */ traversePostOrder(cb, abortCb) { if (typeof cb !== 'function') { From 1f884b48b02ad3c258d315dbf040e835930d5000 Mon Sep 17 00:00:00 2001 From: Eyas Ranjous Date: Thu, 8 Dec 2022 06:48:09 -0300 Subject: [PATCH 4/7] doc --- README.md | 39 ++++++++++++++++++++++++++++++++++++--- 1 file changed, 36 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 26ac85e..258f5d0 100644 --- a/README.md +++ b/README.md @@ -232,7 +232,7 @@ employees.count(); // 7 ### traverseInOrder O(n) -traverses the tree in order (left-node-right). +traverses the tree in order (left-node-right). it also accepts an optional third param as a callback to abort traversal when it returns true. ```js nums.traverseInOrder((node) => console.log(node.getValue())); @@ -256,12 +256,23 @@ employees.traverseInOrder((node) => console.log(node.getValue())); { id: 80 } { id: 90 } */ + +let counter = 0; +const abortCb = () => counter > 1; +employees.traverseInOrder((node) => { + console.log(node.getValue()); + counter += 1; +}, abortCb); +/* + { id: 20 } + { id: 30 } +*/ ``` ### traversePreOrder O(n) -traverses the tree pre order (node-left-right). +traverses the tree pre order (node-left-right). it also accepts an optional third param as a callback to abort traversal when it returns true. ```js nums.traversePreOrder((node) => console.log(node.getValue())); @@ -285,12 +296,23 @@ employees.traversePreOrder((node) => console.log(node.getValue())); { id: 60 } { id: 90 } */ + +let counter = 0; +const abortCb = () => counter > 1; +employees.traversePreOrder((node) => { + console.log(node.getValue()); + counter += 1; +}, abortCb); +/* + { id: 50 } + { id: 30 } +*/ ``` ### traversePostOrder O(n) -traverses the tree post order (left-right-node). +traverses the tree post order (left-right-node). it also accepts an optional third param as a callback to abort traversal when it returns true. ```js nums.traversePostOrder((node) => console.log(node.getValue())); @@ -314,6 +336,17 @@ employees.traversePostOrder((node) => console.log(node.getValue())); { id: 80 } { id: 50 } */ + +let counter = 0; +const abortCb = () => counter > 1; +employees.traversePostOrder((node) => { + console.log(node.getValue()); + counter += 1; +}, abortCb); +/* + { id: 20 } + { id: 40 } +*/ ``` ### remove From 916b8f360783c4fac7e2d75304e6332934290748 Mon Sep 17 00:00:00 2001 From: Eyas Ranjous Date: Thu, 8 Dec 2022 06:52:48 -0300 Subject: [PATCH 5/7] 5.1.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 1af1e3f..433e4be 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@datastructures-js/binary-search-tree", - "version": "5.0.2", + "version": "5.1.0", "description": "binary search tree & avl tree (self balancing tree) implementation in javascript", "main": "index.js", "types": "index.d.ts", From b3cdd882bfa012d7886c1adcbf157aaf594ba208 Mon Sep 17 00:00:00 2001 From: Eyas Ranjous Date: Thu, 8 Dec 2022 06:53:49 -0300 Subject: [PATCH 6/7] v5.1.0 --- CHANGELOG.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index c1b4023..44a902e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,11 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ## [Unreleased] +## [5.1.0] - 2022-12-08 + +### Added +- ability to abort tree traversal using a callback. + ## [5.0.2] - 2022-08-21 ### Fixed From 960a712846879cab9fbe83ba66add8efab528a22 Mon Sep 17 00:00:00 2001 From: Eyas Ranjous Date: Thu, 8 Dec 2022 06:55:01 -0300 Subject: [PATCH 7/7] typo --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 258f5d0..d301b2a 100644 --- a/README.md +++ b/README.md @@ -232,7 +232,7 @@ employees.count(); // 7 ### traverseInOrder O(n) -traverses the tree in order (left-node-right). it also accepts an optional third param as a callback to abort traversal when it returns true. +traverses the tree in order (left-node-right). it also accepts an optional second param as a callback to abort traversal when it returns true. ```js nums.traverseInOrder((node) => console.log(node.getValue())); @@ -272,7 +272,7 @@ employees.traverseInOrder((node) => { ### traversePreOrder O(n) -traverses the tree pre order (node-left-right). it also accepts an optional third param as a callback to abort traversal when it returns true. +traverses the tree pre order (node-left-right). it also accepts an optional second param as a callback to abort traversal when it returns true. ```js nums.traversePreOrder((node) => console.log(node.getValue())); @@ -312,7 +312,7 @@ employees.traversePreOrder((node) => { ### traversePostOrder O(n) -traverses the tree post order (left-right-node). it also accepts an optional third param as a callback to abort traversal when it returns true. +traverses the tree post order (left-right-node). it also accepts an optional second param as a callback to abort traversal when it returns true. ```js nums.traversePostOrder((node) => console.log(node.getValue()));