From a699b097c75c23102473e75a3258103275aaabe2 Mon Sep 17 00:00:00 2001 From: Revone Date: Sun, 20 Oct 2024 16:59:01 +1300 Subject: [PATCH] feat: The leaves method of the binary tree supports both RECURSIVE and ITERATIVE modes. --- .../binary-tree/binary-tree.ts | 100 ++++++++---------- .../data-structures/binary-tree/bst.test.ts | 4 +- .../binary-tree/rb-tree.test.ts | 2 +- 3 files changed, 47 insertions(+), 59 deletions(-) diff --git a/src/data-structures/binary-tree/binary-tree.ts b/src/data-structures/binary-tree/binary-tree.ts index d202183..de5a89e 100644 --- a/src/data-structures/binary-tree/binary-tree.ts +++ b/src/data-structures/binary-tree/binary-tree.ts @@ -1612,24 +1612,56 @@ export class BinaryTree< * Time complexity: O(n) * Space complexity: O(n) * - * The `leaves` function collects and returns the leaves of a binary tree using a specified callback. - * @param {C} callback - The `callback` parameter is a function that will be called for each node in - * the tree. It is a generic type `C` that extends `BTNCallback`, where `NODE` is the - * type of nodes in the tree. The default value for `callback` is ` + * The `leaves` function in TypeScript iterates through a binary tree to find and return the leaf + * nodes based on a specified callback and iteration type. + * @param {C} callback - The `callback` parameter is a function that will be called on each leaf node + * in the binary tree. It is a generic type `C` that extends `BTNCallback`, where `NODE` + * represents a node in the binary tree. The default value for `callback` is * @param {R | BTNKeyOrNodeOrEntry} beginRoot - The `beginRoot` parameter in the `leaves` - * method is used to specify the starting point for collecting leaves in a binary tree. It can be - * either a root node of the tree or a key-value pair or an entry that will be converted to a node. - * If not provided, the default - * @returns The `leaves` method is returning an array of values that are the return type of the - * callback function provided as an argument. + * method is used to specify the starting point for finding and processing the leaves of a binary + * tree. It represents the root node of the binary tree or a specific key, node, or entry within the + * tree from which the search for leaves should begin + * @param {IterationType} iterationType - The `iterationType` parameter in the `leaves` method + * specifies the type of iteration to be performed when collecting the leaves of a binary tree. It + * can have two possible values: + * @returns The `leaves` method returns an array of values that are the result of applying the + * provided callback function to the leaf nodes in the binary tree structure. */ leaves>( callback: C = this._DEFAULT_CALLBACK as C, - beginRoot: R | BTNKeyOrNodeOrEntry = this.root + beginRoot: R | BTNKeyOrNodeOrEntry = this.root, + iterationType: IterationType = this.iterationType ): ReturnType[] { beginRoot = this.ensureNode(beginRoot); - const leaves: ReturnType> = []; - this._collectLeaves(callback, beginRoot, leaves); + const leaves: ReturnType>[] = []; + if (!this.isRealNode(beginRoot)) { + return []; + } + if (iterationType === 'RECURSIVE') { + const dfs = (cur: NODE) => { + if (this.isLeaf(cur)) { + leaves.push(callback(cur)); + } + if (!this.isRealNode(cur.left) && !this.isRealNode(cur.right)) return; + this.isRealNode(cur.left) && dfs(cur.left); + this.isRealNode(cur.right) && dfs(cur.right); + }; + + dfs(beginRoot); + } else { + const queue = new Queue([beginRoot]); + while (queue.size > 0) { + const cur = queue.shift(); + if (this.isRealNode(cur)) { + if (this.isLeaf(cur)) { + leaves.push(callback(cur)); + } + this.isRealNode(cur.left) && queue.push(cur.left); + this.isRealNode(cur.right) && queue.push(cur.right); + } + } + } + return leaves; } @@ -2236,48 +2268,4 @@ export class BinaryTree< return callback; } - - /** - * Time complexity: O(n) - * Space complexity: O(n) - */ - - /** - * Time complexity: O(n) - * Space complexity: O(n) - * - * The function `_collectLeaves` recursively collects leaf nodes in a binary tree using a specified - * callback function. - * @param {C} callback - The `callback` parameter in the `_collectLeaves` method is a function that - * takes a node (of type `NODE` or `null`) as an argument and returns a value. It is a generic type - * `C` that extends the `BTNCallback` type. The default value for ` - * @param node - The `node` parameter in the `_collectLeaves` method represents a binary tree node. - * It can either be a valid node of type `NODE` or `null`. The method checks if the node is a leaf - * node (i.e., it has no left or right children) and collects the - * @param {ReturnType>[]} leaves - The `leaves` parameter in the `_collectLeaves` - * method is an array that stores the return values of the callback function for each leaf node - * encountered during the traversal of the binary tree. It accumulates these values as leaf nodes are - * visited in the tree. - * @returns In the provided code snippet, the method `_collectLeaves` is a recursive function that - * collects leaf nodes in a binary tree. The function takes a callback function `callback`, a node - * `node`, and an array `leaves` as parameters. - */ - protected _collectLeaves>( - callback: C = this._DEFAULT_CALLBACK as C, - node: OptBTNOrNull, - leaves: ReturnType>[] - ): void { - if (!this.isRealNode(node)) { - return; - } - - // If both left and right are NIL, it's a leaf node - if (this.isLeaf(node)) { - leaves.push(callback(node)); - } - - // Recurse for both left and right children - this._collectLeaves(callback, node.left, leaves); - this._collectLeaves(callback, node.right, leaves); - } } diff --git a/test/unit/data-structures/binary-tree/bst.test.ts b/test/unit/data-structures/binary-tree/bst.test.ts index cdfbc3f..4cbe25b 100644 --- a/test/unit/data-structures/binary-tree/bst.test.ts +++ b/test/unit/data-structures/binary-tree/bst.test.ts @@ -1100,7 +1100,7 @@ describe('BST iterative methods test', () => { true ); - expect(balanced.leaves()).toEqual([1, 4, 6, 9]); - expect(balanced.leaves(node => node?.value)).toEqual(['a', 'd', 'f', 'i']); + expect(balanced.leaves()).toEqual([1, 6, 4, 9]); + expect(balanced.leaves(node => node?.value)).toEqual(['a', 'f', 'd', 'i']); }); }); diff --git a/test/unit/data-structures/binary-tree/rb-tree.test.ts b/test/unit/data-structures/binary-tree/rb-tree.test.ts index 9880b7f..3aea976 100644 --- a/test/unit/data-structures/binary-tree/rb-tree.test.ts +++ b/test/unit/data-structures/binary-tree/rb-tree.test.ts @@ -785,7 +785,7 @@ describe('RedBlackTree - _deleteFixup', () => { expect(tree.root?.left?.left?.key).toBe(5); expect(tree.root?.left?.right?.color).toBe('BLACK'); expect(tree.root?.left?.right?.key).toBe(15); - expect(tree.leaves(node => (node === null ? '' : `${node.key} ${node.color}`))).toEqual([ + expect(tree.leaves(node => (node === null ? '' : `${node.key} ${node.color}`), tree.root, 'RECURSIVE')).toEqual([ '8 RED', '15 BLACK', '25 RED',