UNPKG

heap-typed

Version:

Heap. Javascript & Typescript Data Structure.

719 lines (718 loc) 34.4 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.BST = exports.BSTNode = void 0; const binary_tree_1 = require("./binary-tree"); const queue_1 = require("../queue"); const utils_1 = require("../../utils"); class BSTNode extends binary_tree_1.BinaryTreeNode { constructor(key, value) { super(key, value); this.parent = undefined; this._left = undefined; this._right = undefined; } /** * The function returns the value of the `_left` property. * @returns The `_left` property of the current object is being returned. */ get left() { return this._left; } /** * The function sets the left child of a node and updates the parent reference of the child. * @param {OptNode<NODE>} v - The parameter `v` is of type `OptNode<NODE>`. It can either be an * instance of the `NODE` class or `undefined`. */ set left(v) { if (v) { v.parent = this; } this._left = v; } /** * The function returns the right node of a binary tree or undefined if there is no right node. * @returns The method is returning the value of the `_right` property, which is of type `NODE` or * `undefined`. */ get right() { return this._right; } /** * The function sets the right child of a node and updates the parent reference of the child. * @param {OptNode<NODE>} v - The parameter `v` is of type `OptNode<NODE>`. It can either be a * `NODE` object or `undefined`. */ set right(v) { if (v) { v.parent = this; } this._right = v; } } exports.BSTNode = BSTNode; /** * 1. Node Order: Each node's left child has a lesser value, and the right child has a greater value. * 2. Unique Keys: No duplicate keys in a standard BST. * 3. Efficient Search: Enables quick search, minimum, and maximum operations. * 4. Inorder Traversal: Yields nodes in ascending order. * 5. Logarithmic Operations: Ideal operations like insertion, deletion, and searching are O(log n) time-efficient. * 6. Balance Variability: Can become unbalanced; special types maintain balance. * 7. No Auto-Balancing: Standard BSTs don't automatically balance themselves. */ class BST extends binary_tree_1.BinaryTree { /** * This is the constructor function for a Binary Search Tree class in TypeScript. * @param keysNodesEntriesOrRaws - The `keysNodesEntriesOrRaws` parameter is an * iterable that can contain either keys, nodes, entries, or raw elements. These elements will be * added to the binary search tree during the construction of the object. * @param [options] - An optional object that contains additional options for the Binary Search Tree. * It can include a comparator function that defines the order of the elements in the tree. */ constructor(keysNodesEntriesOrRaws = [], options) { super([], options); this._root = undefined; this._DEFAULT_COMPARATOR = (a, b) => { if (typeof a === 'object' || typeof b === 'object') { throw TypeError(`When comparing object types, a custom comparator must be defined in the constructor's options parameter.`); } if (a > b) return 1; if (a < b) return -1; return 0; }; this._comparator = this._DEFAULT_COMPARATOR; if (options) { const { comparator } = options; if (comparator) this._comparator = comparator; } if (keysNodesEntriesOrRaws) this.addMany(keysNodesEntriesOrRaws); } /** * The function returns the root node of a tree structure. * @returns The `_root` property of the object, which is of type `NODE` or `undefined`. */ get root() { return this._root; } /** * The function creates a new BSTNode with the given key and value and returns it. * @param {K} key - The key parameter is of type K, which represents the type of the key for the node * being created. * @param {V} [value] - The "value" parameter is an optional parameter of type V. It represents the * value associated with the key in the node being created. * @returns The method is returning a new instance of the BSTNode class, casted as the NODE type. */ createNode(key, value) { return new BSTNode(key, value); } /** * The function creates a new binary search tree with the specified options. * @param [options] - The `options` parameter is an optional object that allows you to customize the * behavior of the `createTree` method. It accepts a partial `BSTOptions` object, which has the * following properties: * @returns a new instance of the BST class with the provided options. */ createTree(options) { return new BST([], Object.assign({ iterationType: this.iterationType, isMapMode: this._isMapMode, comparator: this._comparator, toEntryFn: this._toEntryFn }, options)); } /** * The function overrides a method and converts a key, value pair or entry or raw element to a node. * @param {BTNRep<K, V, NODE> | R} keyNodeEntryOrRaw - A variable that can be of * type R or BTNRep<K, V, NODE>. It represents either a key, a node, an entry, or a raw * element. * @param {V} [value] - The `value` parameter is an optional value of type `V`. It represents the * value associated with a key in a key-value pair. * @returns either a NODE object or undefined. */ keyValueNodeEntryRawToNodeAndValue(keyNodeEntryOrRaw, value) { const [node, tValue] = super.keyValueNodeEntryRawToNodeAndValue(keyNodeEntryOrRaw, value); if (node === null) return [undefined, undefined]; return [node, tValue !== null && tValue !== void 0 ? tValue : value]; } /** * Time Complexity: O(log n) * Space Complexity: O(log n) * * The function ensures the existence of a node in a data structure and returns it, or undefined if * it doesn't exist. * @param {BTNRep<K, V, NODE> | R} keyNodeEntryOrRaw - The parameter * `keyNodeEntryOrRaw` can accept a value of type `R`, which represents the key, node, * entry, or raw element that needs to be ensured in the tree. * @param {IterationType} [iterationType=ITERATIVE] - The `iterationType` parameter is an optional * parameter that specifies the type of iteration to be used when ensuring a node. It has a default * value of `'ITERATIVE'`. * @returns The method is returning either the node that was ensured or `undefined` if the node could * not be ensured. */ ensureNode(keyNodeEntryOrRaw, iterationType = this.iterationType) { var _a; return (_a = super.ensureNode(keyNodeEntryOrRaw, iterationType)) !== null && _a !== void 0 ? _a : undefined; } /** * The function checks if the input is an instance of the BSTNode class. * @param {BTNRep<K, V, NODE> | R} keyNodeEntryOrRaw - The parameter * `keyNodeEntryOrRaw` can be of type `R` or `BTNRep<K, V, NODE>`. * @returns a boolean value indicating whether the input parameter `keyNodeEntryOrRaw` is * an instance of the `BSTNode` class. */ isNode(keyNodeEntryOrRaw) { return keyNodeEntryOrRaw instanceof BSTNode; } /** * The function "override isKey" checks if a key is comparable based on a given comparator. * @param {any} key - The `key` parameter is a value that will be checked to determine if it is of * type `K`. * @returns The `override isKey(key: any): key is K` function is returning a boolean value based on * the result of the `isComparable` function with the condition `this.comparator !== * this._DEFAULT_COMPARATOR`. */ isKey(key) { return (0, utils_1.isComparable)(key, this.comparator !== this._DEFAULT_COMPARATOR); } /** * Time Complexity: O(log n) * Space Complexity: O(1) * * The `add` function in TypeScript adds a new node to a binary search tree based on the key value. * @param {BTNRep<K, V, NODE> | R} keyNodeEntryOrRaw - The parameter * `keyNodeEntryOrRaw` can accept a value of type `R` or `BTNRep<K, V, NODE>`. * @param {V} [value] - The `value` parameter is an optional value that can be associated with the * key in the binary search tree. If provided, it will be stored in the node along with the key. * @returns a boolean value. */ add(keyNodeEntryOrRaw, value) { const [newNode, newValue] = this.keyValueNodeEntryRawToNodeAndValue(keyNodeEntryOrRaw, value); if (newNode === undefined) return false; if (this._root === undefined) { this._setRoot(newNode); if (this._isMapMode) this._setValue(newNode === null || newNode === void 0 ? void 0 : newNode.key, newValue); this._size++; return true; } let current = this._root; while (current !== undefined) { if (this.comparator(current.key, newNode.key) === 0) { this._replaceNode(current, newNode); return true; } else if (this.comparator(current.key, newNode.key) > 0) { if (current.left === undefined) { current.left = newNode; if (this._isMapMode) this._setValue(newNode === null || newNode === void 0 ? void 0 : newNode.key, newValue); this._size++; return true; } current = current.left; } else { if (current.right === undefined) { current.right = newNode; if (this._isMapMode) this._setValue(newNode === null || newNode === void 0 ? void 0 : newNode.key, newValue); this._size++; return true; } current = current.right; } } return false; } /** * Time Complexity: O(k log n) * Space Complexity: O(k + log n) * * The `addMany` function in TypeScript adds multiple keys or nodes to a data structure and returns * an array indicating whether each key or node was successfully inserted. * @param keysNodesEntriesOrRaws - An iterable containing keys, nodes, entries, or raw * elements to be added to the data structure. * @param [values] - An optional iterable of values to be associated with the keys or nodes being * added. If provided, the values will be assigned to the corresponding keys or nodes in the same * order. If not provided, undefined will be assigned as the value for each key or node. * @param [isBalanceAdd=true] - A boolean flag indicating whether the tree should be balanced after * adding the elements. If set to true, the tree will be balanced using a binary search tree * algorithm. If set to false, the elements will be added without balancing the tree. The default * value is true. * @param {IterationType} iterationType - The `iterationType` parameter is an optional parameter that * specifies the type of iteration to use when adding multiple keys or nodes to the binary search * tree. It can have two possible values: * @returns The function `addMany` returns an array of booleans indicating whether each element was * successfully inserted into the data structure. */ addMany(keysNodesEntriesOrRaws, values, isBalanceAdd = true, iterationType = this.iterationType) { const inserted = []; let valuesIterator; if (values) { valuesIterator = values[Symbol.iterator](); } if (!isBalanceAdd) { for (const kve of keysNodesEntriesOrRaws) { const value = valuesIterator === null || valuesIterator === void 0 ? void 0 : valuesIterator.next().value; inserted.push(this.add(kve, value)); } return inserted; } const realBTNExemplars = []; let i = 0; for (const kve of keysNodesEntriesOrRaws) { realBTNExemplars.push({ key: kve, value: valuesIterator === null || valuesIterator === void 0 ? void 0 : valuesIterator.next().value, orgIndex: i }); i++; } let sorted = []; sorted = realBTNExemplars.sort(({ key: a }, { key: b }) => { let keyA, keyB; if (this.isEntry(a)) keyA = a[0]; else if (this.isRealNode(a)) keyA = a.key; else if (this._toEntryFn) { keyA = this._toEntryFn(a)[0]; } else { keyA = a; } if (this.isEntry(b)) keyB = b[0]; else if (this.isRealNode(b)) keyB = b.key; else if (this._toEntryFn) { keyB = this._toEntryFn(b)[0]; } else { keyB = b; } if (keyA !== undefined && keyA !== null && keyB !== undefined && keyB !== null) { return this.comparator(keyA, keyB); } return 0; }); const _dfs = (arr) => { if (arr.length === 0) return; const mid = Math.floor((arr.length - 1) / 2); const { key, value, orgIndex } = arr[mid]; inserted[orgIndex] = this.add(key, value); _dfs(arr.slice(0, mid)); _dfs(arr.slice(mid + 1)); }; const _iterate = () => { const n = sorted.length; const stack = [[0, n - 1]]; while (stack.length > 0) { const popped = stack.pop(); if (popped) { const [l, r] = popped; if (l <= r) { const m = l + Math.floor((r - l) / 2); const { key, value, orgIndex } = sorted[m]; inserted[orgIndex] = this.add(key, value); stack.push([m + 1, r]); stack.push([l, m - 1]); } } } }; if (iterationType === 'RECURSIVE') { _dfs(sorted); } else { _iterate(); } return inserted; } /** * Time Complexity: O(log n) * Space Complexity: O(k + log n) * * The function `getNodes` in TypeScript overrides the base class method to retrieve nodes based on a * given keyNodeEntryRawOrPredicate and iteration type. * @param {BTNRep<K, V, NODE> | R | NodePredicate<NODE>} keyNodeEntryRawOrPredicate - The `keyNodeEntryRawOrPredicate` * parameter in the `getNodes` method is used to filter the nodes that will be returned. It can be a * key, a node, an entry, or a custom keyNodeEntryRawOrPredicate function that determines whether a node should be * included in the result. * @param [onlyOne=false] - The `onlyOne` parameter in the `getNodes` method is a boolean flag that * determines whether to return only the first node that matches the keyNodeEntryRawOrPredicate (`true`) or all nodes * that match the keyNodeEntryRawOrPredicate (`false`). If `onlyOne` is set to `true`, the method will stop iterating * and * @param {BTNRep<K, V, NODE> | R} startNode - The `startNode` parameter in the * `getNodes` method is used to specify the starting point for traversing the tree when searching for * nodes that match a given keyNodeEntryRawOrPredicate. It represents the root node of the subtree where the search * should begin. If not explicitly provided, the default value for `begin * @param {IterationType} iterationType - The `iterationType` parameter in the `getNodes` method * specifies the type of iteration to be performed when traversing the nodes of a binary tree. It can * have two possible values: * @returns The `getNodes` method returns an array of nodes that satisfy the given keyNodeEntryRawOrPredicate. */ getNodes(keyNodeEntryRawOrPredicate, onlyOne = false, startNode = this._root, iterationType = this.iterationType) { if (keyNodeEntryRawOrPredicate === undefined) return []; if (keyNodeEntryRawOrPredicate === null) return []; startNode = this.ensureNode(startNode); if (!startNode) return []; const callback = this._ensurePredicate(keyNodeEntryRawOrPredicate); const ans = []; if (iterationType === 'RECURSIVE') { const dfs = (cur) => { if (callback(cur)) { ans.push(cur); if (onlyOne) return; } if (!this.isRealNode(cur.left) && !this.isRealNode(cur.right)) return; if (!this._isPredicate(keyNodeEntryRawOrPredicate)) { const benchmarkKey = this._getKey(keyNodeEntryRawOrPredicate); if (this.isRealNode(cur.left) && benchmarkKey !== null && benchmarkKey !== undefined && this.comparator(cur.key, benchmarkKey) > 0) dfs(cur.left); if (this.isRealNode(cur.right) && benchmarkKey !== null && benchmarkKey !== undefined && this.comparator(cur.key, benchmarkKey) < 0) dfs(cur.right); } else { if (this.isRealNode(cur.left)) dfs(cur.left); if (this.isRealNode(cur.right)) dfs(cur.right); } }; dfs(startNode); } else { const stack = [startNode]; while (stack.length > 0) { const cur = stack.pop(); if (callback(cur)) { ans.push(cur); if (onlyOne) return ans; } if (!this._isPredicate(keyNodeEntryRawOrPredicate)) { const benchmarkKey = this._getKey(keyNodeEntryRawOrPredicate); if (this.isRealNode(cur.right) && benchmarkKey !== null && benchmarkKey !== undefined && this.comparator(cur.key, benchmarkKey) < 0) stack.push(cur.right); if (this.isRealNode(cur.left) && benchmarkKey !== null && benchmarkKey !== undefined && this.comparator(cur.key, benchmarkKey) > 0) stack.push(cur.left); } else { if (this.isRealNode(cur.right)) stack.push(cur.right); if (this.isRealNode(cur.left)) stack.push(cur.left); } } } return ans; } /** * Time Complexity: O(log n) * Space Complexity: O(1) * * This function retrieves a node based on a given keyNodeEntryRawOrPredicate within a binary search tree structure. * @param {BTNRep<K, V, NODE> | R | NodePredicate<NODE>} keyNodeEntryRawOrPredicate - The `keyNodeEntryRawOrPredicate` * parameter can be of type `BTNRep<K, V, NODE>`, `R`, or `NodePredicate<NODE>`. * @param {R | BSTNOptKeyOrNode<K, NODE>} startNode - The `startNode` parameter in the `getNode` method * is used to specify the starting point for searching nodes in the binary search tree. If no * specific starting point is provided, the default value is set to `this._root`, which is the root * node of the binary search tree. * @param {IterationType} iterationType - The `iterationType` parameter in the `getNode` method is a * parameter that specifies the type of iteration to be used. It has a default value of * `this.iterationType`, which means it will use the iteration type defined in the class instance if * no value is provided when calling the method. * @returns The `getNode` method is returning an optional binary search tree node (`OptNode<NODE>`). * It is using the `getNodes` method to find the node based on the provided keyNodeEntryRawOrPredicate, beginning at * the specified root node (`startNode`) and using the specified iteration type. The method then * returns the first node found or `undefined` if no node is found. */ getNode(keyNodeEntryRawOrPredicate, startNode = this._root, iterationType = this.iterationType) { var _a; return (_a = this.getNodes(keyNodeEntryRawOrPredicate, true, startNode, iterationType)[0]) !== null && _a !== void 0 ? _a : undefined; } /** * Time Complexity: O(log n) * Space Complexity: O(1) * * The function `getNodeByKey` returns a node with a specific key from a tree data structure. * @param {K} key - The key parameter is the value used to search for a specific node in the tree. It * is typically a unique identifier or a value that can be used to determine the position of the node * in the tree structure. * @param {IterationType} [iterationType=ITERATIVE] - The `iterationType` parameter is an optional * parameter that specifies the type of iteration to be used when searching for a node in the tree. * It has a default value of `'ITERATIVE'`. * @returns The method is returning a NODE object or undefined. */ getNodeByKey(key, iterationType = this.iterationType) { return this.getNode(key, this._root, iterationType); } /** * Time complexity: O(n) * Space complexity: O(n) * * The function overrides the depth-first search method and returns an array of the return types of * the callback function. * @param {C} callback - The `callback` parameter is a function that will be called for each node * during the depth-first search traversal. It is an optional parameter and defaults to * `this._DEFAULT_NODE_CALLBACK`. The type `C` represents the type of the callback function. * @param {DFSOrderPattern} [pattern=IN] - The "pattern" parameter in the code snippet refers to the * order in which the Depth-First Search (DFS) algorithm visits the nodes in a tree or graph. It can * take one of the following values: * @param {BTNRep<K, V, NODE> | R} startNode - The `startNode` parameter is the starting * point for the depth-first search traversal. It can be either a root node, a key-value pair, or a * node entry. If not specified, the default value is the root of the tree. * @param {IterationType} [iterationType=ITERATIVE] - The `iterationType` parameter specifies the * type of iteration to be used during the Depth-First Search (DFS) traversal. It can have one of the * following values: * @returns The method is returning an array of the return type of the callback function. */ dfs(callback = this._DEFAULT_NODE_CALLBACK, pattern = 'IN', startNode = this._root, iterationType = this.iterationType) { return super.dfs(callback, pattern, startNode, iterationType); } /** * Time complexity: O(n) * Space complexity: O(n) * * The function overrides the breadth-first search method and returns an array of the return types of * the callback function. * @param {C} callback - The `callback` parameter is a function that will be called for each node * visited during the breadth-first search. It should take a single argument, which is the current * node being visited, and it can return a value of any type. * @param {BTNRep<K, V, NODE> | R} startNode - The `startNode` parameter is the starting * point for the breadth-first search. It can be either a root node, a key-value pair, or an entry * object. If no value is provided, the default value is the root of the tree. * @param {IterationType} iterationType - The `iterationType` parameter is used to specify the type * of iteration to be performed during the breadth-first search (BFS) traversal. It can have one of * the following values: * @returns an array of the return type of the callback function. */ bfs(callback = this._DEFAULT_NODE_CALLBACK, startNode = this._root, iterationType = this.iterationType) { return super.bfs(callback, startNode, iterationType, false); } /** * Time complexity: O(n) * Space complexity: O(n) * * The function overrides the listLevels method from the superclass and returns an array of arrays * containing the results of the callback function applied to each level of the tree. * @param {C} callback - The `callback` parameter is a generic type `C` that extends * `NodeCallback<NODE>`. It represents a callback function that will be called for each node in the * tree during the iteration process. * @param {BTNRep<K, V, NODE> | R} startNode - The `startNode` parameter is the starting * point for listing the levels of the binary tree. It can be either a root node of the tree, a * key-value pair representing a node in the tree, or a key representing a node in the tree. If no * value is provided, the root of * @param {IterationType} iterationType - The `iterationType` parameter is used to specify the type * of iteration to be performed on the tree. It can have one of the following values: * @returns The method is returning a two-dimensional array of the return type of the callback * function. */ listLevels(callback = this._DEFAULT_NODE_CALLBACK, startNode = this._root, iterationType = this.iterationType) { return super.listLevels(callback, startNode, iterationType, false); } /** * Time complexity: O(n) * Space complexity: O(n) * * The `lesserOrGreaterTraverse` function traverses a binary tree and applies a callback function to * each node that meets a certain condition based on a target node and a comparison value. * @param {C} callback - The `callback` parameter is a function that will be called for each node * that meets the condition specified by the `lesserOrGreater` parameter. It takes a single argument, * which is the current node being traversed, and returns a value of any type. * @param {CP} lesserOrGreater - The `lesserOrGreater` parameter is used to determine whether to * traverse nodes that are lesser, greater, or both than the `targetNode`. It accepts the values -1, * 0, or 1, where: * @param {BTNRep<K, V, NODE> | R} targetNode - The `targetNode` parameter is the node in * the binary tree that you want to start traversing from. It can be specified either by providing * the key of the node, the node itself, or an entry containing the key and value of the node. If no * `targetNode` is provided, * @param {IterationType} iterationType - The `iterationType` parameter determines the type of * traversal to be performed on the binary tree. It can have two possible values: * @returns The function `lesserOrGreaterTraverse` returns an array of values of type * `ReturnType<C>`, which is the return type of the callback function passed as an argument. */ lesserOrGreaterTraverse(callback = this._DEFAULT_NODE_CALLBACK, lesserOrGreater = -1, targetNode = this._root, iterationType = this.iterationType) { const targetNodeEnsured = this.ensureNode(targetNode); const ans = []; if (!this._root) return ans; if (!targetNodeEnsured) return ans; const targetKey = targetNodeEnsured.key; if (iterationType === 'RECURSIVE') { const dfs = (cur) => { const compared = this.comparator(cur.key, targetKey); if (Math.sign(compared) === lesserOrGreater) ans.push(callback(cur)); if (this.isRealNode(cur.left)) dfs(cur.left); if (this.isRealNode(cur.right)) dfs(cur.right); }; dfs(this._root); return ans; } else { const queue = new queue_1.Queue([this._root]); while (queue.size > 0) { const cur = queue.shift(); if (this.isRealNode(cur)) { const compared = this.comparator(cur.key, targetKey); if (Math.sign(compared) === lesserOrGreater) ans.push(callback(cur)); if (this.isRealNode(cur.left)) queue.push(cur.left); if (this.isRealNode(cur.right)) queue.push(cur.right); } } return ans; } } /** * Time complexity: O(n) * Space complexity: O(n) * * The `perfectlyBalance` function takes an optional `iterationType` parameter and returns `true` if * the binary search tree is perfectly balanced, otherwise it returns `false`. * @param {IterationType} iterationType - The `iterationType` parameter is an optional parameter that * specifies the type of iteration to use when building a balanced binary search tree. It has a * default value of `this.iterationType`, which means it will use the iteration type specified in the * current instance of the class. * @returns The function `perfectlyBalance` returns a boolean value. */ perfectlyBalance(iterationType = this.iterationType) { const sorted = this.dfs(node => node, 'IN'), n = sorted.length; this._clearNodes(); if (sorted.length < 1) return false; if (iterationType === 'RECURSIVE') { const buildBalanceBST = (l, r) => { if (l > r) return; const m = l + Math.floor((r - l) / 2); const midNode = sorted[m]; if (this._isMapMode) this.add(midNode.key); else this.add([midNode.key, midNode.value]); buildBalanceBST(l, m - 1); buildBalanceBST(m + 1, r); }; buildBalanceBST(0, n - 1); return true; } else { const stack = [[0, n - 1]]; while (stack.length > 0) { const popped = stack.pop(); if (popped) { const [l, r] = popped; if (l <= r) { const m = l + Math.floor((r - l) / 2); const midNode = sorted[m]; if (this._isMapMode) this.add(midNode.key); else this.add([midNode.key, midNode.value]); stack.push([m + 1, r]); stack.push([l, m - 1]); } } } return true; } } /** * Time Complexity: O(n) * Space Complexity: O(log n) * * The function `isAVLBalanced` checks if a binary tree is AVL balanced using either a recursive or * iterative approach. * @param {IterationType} iterationType - The `iterationType` parameter is an optional parameter that * specifies the type of iteration to use when checking if the AVL tree is balanced. It has a default * value of `this.iterationType`, which means it will use the iteration type specified in the current * instance of the AVL tree. * @returns a boolean value. */ isAVLBalanced(iterationType = this.iterationType) { if (!this._root) return true; let balanced = true; if (iterationType === 'RECURSIVE') { const _height = (cur) => { if (!cur) return 0; const leftHeight = _height(cur.left), rightHeight = _height(cur.right); if (Math.abs(leftHeight - rightHeight) > 1) balanced = false; return Math.max(leftHeight, rightHeight) + 1; }; _height(this._root); } else { const stack = []; let node = this._root, last = undefined; const depths = new Map(); while (stack.length > 0 || node) { if (node) { stack.push(node); node = node.left; } else { node = stack[stack.length - 1]; if (!node.right || last === node.right) { node = stack.pop(); if (node) { const left = node.left ? depths.get(node.left) : -1; const right = node.right ? depths.get(node.right) : -1; if (Math.abs(left - right) > 1) return false; depths.set(node, 1 + Math.max(left, right)); last = node; node = undefined; } } else node = node.right; } } } return balanced; } /** * The function returns the value of the _comparator property. * @returns The `_comparator` property is being returned. */ get comparator() { return this._comparator; } /** * The function sets the root of a tree-like structure and updates the parent property of the new * root. * @param {OptNode<NODE>} v - v is a parameter of type NODE or undefined. */ _setRoot(v) { if (v) { v.parent = undefined; } this._root = v; } } exports.BST = BST;