heap-typed
Version:
Heap. Javascript & Typescript Data Structure.
719 lines (718 loc) • 34.4 kB
JavaScript
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;
;