UNPKG

tree-multimap-typed

Version:
414 lines (413 loc) 20.3 kB
/** * data-structure-typed * * @author Pablo Zeng * @copyright Copyright (c) 2022 Pablo Zeng <zrwusa@gmail.com> * @license MIT License */ import type { BinaryTreeOptions, BSTNOptKeyOrNode, BSTOptions, BTNRep, Comparable, Comparator, CP, DFSOrderPattern, EntryCallback, IterationType, NodeCallback, NodePredicate, OptNode } from '../../types'; import { BinaryTree, BinaryTreeNode } from './binary-tree'; import { IBinaryTree } from '../../interfaces'; import { Range } from '../../common'; /** * Represents a Node in a Binary Search Tree. * * @template K - The type of the key. * @template V - The type of the value. */ export declare class BSTNode<K = any, V = any> extends BinaryTreeNode<K, V> { parent?: BSTNode<K, V>; /** * Creates an instance of BSTNode. * @remarks Time O(1), Space O(1) * * @param key - The key of the node. * @param [value] - The value associated with the key. */ constructor(key: K, value?: V); _left?: BSTNode<K, V> | null | undefined; /** * Gets the left child of the node. * @remarks Time O(1), Space O(1) * * @returns The left child. */ get left(): BSTNode<K, V> | null | undefined; /** * Sets the left child of the node and updates its parent reference. * @remarks Time O(1), Space O(1) * * @param v - The node to set as the left child. */ set left(v: BSTNode<K, V> | null | undefined); _right?: BSTNode<K, V> | null | undefined; /** * Gets the right child of the node. * @remarks Time O(1), Space O(1) * * @returns The right child. */ get right(): BSTNode<K, V> | null | undefined; /** * Sets the right child of the node and updates its parent reference. * @remarks Time O(1), Space O(1) * * @param v - The node to set as the right child. */ set right(v: BSTNode<K, V> | null | undefined); } /** * Represents a Binary Search Tree (BST). * Keys are ordered, allowing for faster search operations compared to a standard Binary Tree. * @template K - The type of the key. * @template V - The type of the value. * @template R - The type of the raw data object (if using `toEntryFn`). * * 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. * @example * // Merge 3 sorted datasets * const dataset1 = new BST<number, string>([ * [1, 'A'], * [7, 'G'] * ]); * const dataset2 = [ * [2, 'B'], * [6, 'F'] * ]; * const dataset3 = new BST<number, string>([ * [3, 'C'], * [5, 'E'], * [4, 'D'] * ]); * * // Merge datasets into a single BinarySearchTree * const merged = new BST<number, string>(dataset1); * merged.addMany(dataset2); * merged.merge(dataset3); * * // Verify merged dataset is in sorted order * console.log([...merged.values()]); // ['A', 'B', 'C', 'D', 'E', 'F', 'G'] * @example * // Find elements in a range * const bst = new BST<number>([10, 5, 15, 3, 7, 12, 18]); * console.log(bst.search(new Range(5, 10))); // [5, 7, 10] * console.log(bst.rangeSearch([4, 12], node => node.key.toString())); // ['5', '7', '10', '12'] * console.log(bst.search(new Range(4, 12, true, false))); // [5, 7, 10] * console.log(bst.rangeSearch([15, 20])); // [15, 18] * console.log(bst.search(new Range(15, 20, false))); // [18] * @example * // Find lowest common ancestor * const bst = new BST<number>([20, 10, 30, 5, 15, 25, 35, 3, 7, 12, 18]); * * // LCA helper function * const findLCA = (num1: number, num2: number): number | undefined => { * const path1 = bst.getPathToRoot(num1); * const path2 = bst.getPathToRoot(num2); * // Find the first common ancestor * return findFirstCommon(path1, path2); * }; * * function findFirstCommon(arr1: number[], arr2: number[]): number | undefined { * for (const num of arr1) { * if (arr2.indexOf(num) !== -1) { * return num; * } * } * return undefined; * } * * // Assertions * console.log(findLCA(3, 10)); // 7 * console.log(findLCA(5, 35)); // 15 * console.log(findLCA(20, 30)); // 25 */ export declare class BST<K = any, V = any, R extends object = object> extends BinaryTree<K, V, R> implements IBinaryTree<K, V, R> { /** * Creates an instance of BST. * @remarks Time O(N log N) or O(N^2) depending on `isBalanceAdd` in `addMany` and input order. Space O(N). * * @param [keysNodesEntriesOrRaws=[]] - An iterable of items to add. * @param [options] - Configuration options for the BST, including comparator. */ constructor(keysNodesEntriesOrRaws?: Iterable<K | BSTNode<K, V> | [K | null | undefined, V | undefined] | null | undefined | R>, options?: BSTOptions<K, V, R>); protected _root?: BSTNode<K, V>; /** * Gets the root node of the tree. * @remarks Time O(1) * * @returns The root node. */ get root(): OptNode<BSTNode<K, V>>; protected _isReverse: boolean; /** * Gets whether the tree's comparison logic is reversed. * @remarks Time O(1) * * @returns True if the tree is reversed (e.g., a max-heap logic). */ get isReverse(): boolean; /** * The default comparator function. * @remarks Time O(1) (or O(C) if `specifyComparable` is used, C is complexity of that function). */ protected _comparator: Comparator<K>; /** * Gets the comparator function used by the tree. * @remarks Time O(1) * * @returns The comparator function. */ get comparator(): Comparator<K>; protected _specifyComparable?: (key: K) => Comparable; /** * Gets the function used to extract a comparable value from a complex key. * @remarks Time O(1) * * @returns The key-to-comparable conversion function. */ get specifyComparable(): ((key: K) => Comparable) | undefined; /** * (Protected) Creates a new BST node. * @remarks Time O(1), Space O(1) * * @param key - The key for the new node. * @param [value] - The value for the new node (used if not in Map mode). * @returns The newly created BSTNode. */ _createNode(key: K, value?: V): BSTNode<K, V>; /** * Ensures the input is a node. If it's a key or entry, it searches for the node. * @remarks Time O(log N) (height of the tree), O(N) worst-case. * * @param keyNodeOrEntry - The item to resolve to a node. * @param [iterationType=this.iterationType] - The traversal method to use if searching. * @returns The resolved node, or undefined if not found. */ ensureNode(keyNodeOrEntry: K | BSTNode<K, V> | [K | null | undefined, V | undefined] | null | undefined, iterationType?: IterationType): OptNode<BSTNode<K, V>>; /** * Checks if the given item is a `BSTNode` instance. * @remarks Time O(1), Space O(1) * * @param keyNodeOrEntry - The item to check. * @returns True if it's a BSTNode, false otherwise. */ isNode(keyNodeOrEntry: K | BSTNode<K, V> | [K | null | undefined, V | undefined] | null | undefined): keyNodeOrEntry is BSTNode<K, V>; /** * Checks if the given key is valid (comparable). * @remarks Time O(1) * * @param key - The key to validate. * @returns True if the key is valid, false otherwise. */ isValidKey(key: any): key is K; /** * Performs a Depth-First Search (DFS) traversal. * @remarks Time O(N), visits every node. Space O(log N) for the call/explicit stack. O(N) worst-case. * * @template C - The type of the callback function. * @param [callback=this._DEFAULT_NODE_CALLBACK] - Function to call on each node. * @param [pattern='IN'] - The traversal order ('IN', 'PRE', 'POST'). * @param [onlyOne=false] - If true, stops after the first callback. * @param [startNode=this._root] - The node to start from. * @param [iterationType=this.iterationType] - The traversal method. * @returns An array of callback results. */ dfs<C extends NodeCallback<BSTNode<K, V>>>(callback?: C, pattern?: DFSOrderPattern, onlyOne?: boolean, startNode?: K | BSTNode<K, V> | [K | null | undefined, V | undefined] | null | undefined, iterationType?: IterationType): ReturnType<C>[]; /** * Performs a Breadth-First Search (BFS) or Level-Order traversal. * @remarks Time O(N), visits every node. Space O(N) in the worst case for the queue. * * @template C - The type of the callback function. * @param [callback=this._DEFAULT_NODE_CALLBACK] - Function to call on each node. * @param [startNode=this._root] - The node to start from. * @param [iterationType=this.iterationType] - The traversal method. * @returns An array of callback results. */ bfs<C extends NodeCallback<BSTNode<K, V>>>(callback?: C, startNode?: K | BSTNode<K, V> | [K | null | undefined, V | undefined] | null | undefined, iterationType?: IterationType): ReturnType<C>[]; /** * Returns a 2D array of nodes, grouped by level. * @remarks Time O(N), visits every node. Space O(N) for the result array and the queue/stack. * * @template C - The type of the callback function. * @param [callback=this._DEFAULT_NODE_CALLBACK] - Function to call on each node. * @param [startNode=this._root] - The node to start from. * @param [iterationType=this.iterationType] - The traversal method. * @returns A 2D array of callback results. */ listLevels<C extends NodeCallback<BSTNode<K, V>>>(callback?: C, startNode?: K | BSTNode<K, V> | [K | null | undefined, V | undefined] | null | undefined, iterationType?: IterationType): ReturnType<C>[][]; /** * Gets the first node matching a predicate. * @remarks Time O(log N) if searching by key, O(N) if searching by predicate. Space O(log N) or O(N). * * @param keyNodeEntryOrPredicate - The key, node, entry, or predicate function to search for. * @param [startNode=this._root] - The node to start the search from. * @param [iterationType=this.iterationType] - The traversal method. * @returns The first matching node, or undefined if not found. */ getNode(keyNodeEntryOrPredicate: K | BSTNode<K, V> | [K | null | undefined, V | undefined] | null | undefined | NodePredicate<BSTNode<K, V>>, startNode?: BSTNOptKeyOrNode<K, BSTNode<K, V>>, iterationType?: IterationType): OptNode<BSTNode<K, V>>; /** * Searches the tree for nodes matching a predicate, key, or range. * @remarks This is an optimized search for a BST. If searching by key or range, it prunes branches. * Time O(H + M) for key/range search (H=height, M=matches). O(N) for predicate search. * Space O(log N) for the stack. * * @template C - The type of the callback function. * @param keyNodeEntryOrPredicate - The key, node, entry, predicate, or range to search for. * @param [onlyOne=false] - If true, stops after finding the first match. * @param [callback=this._DEFAULT_NODE_CALLBACK] - A function to call on matching nodes. * @param [startNode=this._root] - The node to start the search from. * @param [iterationType=this.iterationType] - Whether to use 'RECURSIVE' or 'ITERATIVE' search. * @returns An array of results from the callback function for each matching node. */ search<C extends NodeCallback<BSTNode<K, V>>>(keyNodeEntryOrPredicate: K | BSTNode<K, V> | [K | null | undefined, V | undefined] | null | undefined | NodePredicate<BSTNode<K, V>> | Range<K>, onlyOne?: boolean, callback?: C, startNode?: K | BSTNode<K, V> | [K | null | undefined, V | undefined] | null | undefined, iterationType?: IterationType): ReturnType<C>[]; /** * Performs an optimized search for nodes within a given key range. * @remarks Time O(H + M), where H is tree height and M is the number of matches. * * @template C - The type of the callback function. * @param range - A `Range` object or a `[low, high]` tuple. * @param [callback=this._DEFAULT_NODE_CALLBACK] - A function to call on matching nodes. * @param [startNode=this._root] - The node to start the search from. * @param [iterationType=this.iterationType] - The traversal method. * @returns An array of callback results. */ rangeSearch<C extends NodeCallback<BSTNode<K, V>>>(range: Range<K> | [K, K], callback?: C, startNode?: K | BSTNode<K, V> | [K | null | undefined, V | undefined] | null | undefined, iterationType?: IterationType): ReturnType<C>[]; /** * Adds a new node to the BST based on key comparison. * @remarks Time O(log N), where H is tree height. O(N) worst-case (unbalanced tree), O(log N) average. Space O(1). * * @param keyNodeOrEntry - The key, node, or entry to add. * @param [value] - The value, if providing just a key. * @returns True if the addition was successful, false otherwise. */ add(keyNodeOrEntry: K | BSTNode<K, V> | [K | null | undefined, V | undefined] | null | undefined, value?: V): boolean; /** * Adds multiple items to the tree. * @remarks If `isBalanceAdd` is true, sorts the input and builds a balanced tree. Time O(N log N) (due to sort and balanced add). * If false, adds items one by one. Time O(N * H), which is O(N^2) worst-case. * Space O(N) for sorting and recursion/iteration stack. * * @param keysNodesEntriesOrRaws - An iterable of items to add. * @param [values] - An optional parallel iterable of values. * @param [isBalanceAdd=true] - If true, builds a balanced tree from the items. * @param [iterationType=this.iterationType] - The traversal method for balanced add (recursive or iterative). * @returns An array of booleans indicating the success of each individual `add` operation. */ addMany(keysNodesEntriesOrRaws: Iterable<R | BTNRep<K, V, BSTNode<K, V>>>, values?: Iterable<V | undefined>, isBalanceAdd?: boolean, iterationType?: IterationType): boolean[]; /** * Traverses the tree and returns nodes that are lesser or greater than a target node. * @remarks Time O(N), as it performs a full traversal. Space O(log N) or O(N). * * @template C - The type of the callback function. * @param [callback=this._DEFAULT_NODE_CALLBACK] - Function to call on matching nodes. * @param [lesserOrGreater=-1] - -1 for lesser, 1 for greater, 0 for equal. * @param [targetNode=this._root] - The node to compare against. * @param [iterationType=this.iterationType] - The traversal method. * @returns An array of callback results. */ lesserOrGreaterTraverse<C extends NodeCallback<BSTNode<K, V>>>(callback?: C, lesserOrGreater?: CP, targetNode?: K | BSTNode<K, V> | [K | null | undefined, V | undefined] | null | undefined, iterationType?: IterationType): ReturnType<C>[]; /** * Rebuilds the tree to be perfectly balanced. * @remarks Time O(N) (O(N) for DFS, O(N) for sorted build). Space O(N) for node array and recursion stack. * * @param [iterationType=this.iterationType] - The traversal method for the initial node export. * @returns True if successful, false if the tree was empty. */ perfectlyBalance(iterationType?: IterationType): boolean; /** * Checks if the tree meets the AVL balance condition (height difference <= 1). * @remarks Time O(N), as it must visit every node to compute height. Space O(log N) for recursion or O(N) for iterative map. * * @param [iterationType=this.iterationType] - The traversal method. * @returns True if the tree is AVL balanced, false otherwise. */ isAVLBalanced(iterationType?: IterationType): boolean; /** * Creates a new BST by mapping each [key, value] pair to a new entry. * @remarks Time O(N * H), where N is nodes in this tree, and H is height of the new tree during insertion. * Space O(N) for the new tree. * * @template MK - New key type. * @template MV - New value type. * @template MR - New raw type. * @param callback - A function to map each [key, value] pair. * @param [options] - Options for the new BST. * @param [thisArg] - `this` context for the callback. * @returns A new, mapped BST. */ map<MK = K, MV = V, MR extends object = object>(callback: EntryCallback<K, V | undefined, [MK, MV]>, options?: Partial<BinaryTreeOptions<MK, MV, MR>>, thisArg?: unknown): BST<MK, MV, MR>; /** * Deletes the first node found that satisfies the predicate. * @remarks Performs an in-order traversal. Time O(N) worst-case (O(log N) to find + O(log N) to delete). Space O(log N) for stack. * * @param predicate - A function to test each [key, value] pair. * @returns True if a node was deleted, false otherwise. */ deleteWhere(predicate: (key: K, value: V | undefined, index: number, tree: this) => boolean): boolean; /** * (Protected) Creates a new, empty instance of the same BST constructor. * @remarks Time O(1) * * @template TK, TV, TR - Generic types for the new instance. * @param [options] - Options for the new BST. * @returns A new, empty BST. */ protected _createInstance<TK = K, TV = V, TR extends object = R>(options?: Partial<BSTOptions<TK, TV, TR>>): this; /** * (Protected) Creates a new instance of the same BST constructor, potentially with different generic types. * @remarks Time O(N log N) or O(N^2) (from constructor) due to processing the iterable. * * @template TK, TV, TR - Generic types for the new instance. * @param [iter=[]] - An iterable to populate the new BST. * @param [options] - Options for the new BST. * @returns A new BST. */ protected _createLike<TK = K, TV = V, TR extends object = R>(iter?: Iterable<TK | BSTNode<TK, TV> | [TK | null | undefined, TV | undefined] | null | undefined | TR>, options?: Partial<BSTOptions<TK, TV, TR>>): BST<TK, TV, TR>; /** * (Protected) Snapshots the current BST's configuration options. * @remarks Time O(1) * * @template TK, TV, TR - Generic types for the options. * @returns The options object. */ protected _snapshotOptions<TK = K, TV = V, TR extends object = R>(): BSTOptions<TK, TV, TR>; /** * (Protected) Converts a key, node, or entry into a standardized [node, value] tuple. * @remarks Time O(1) * * @param keyNodeOrEntry - The input item. * @param [value] - An optional value (used if input is just a key). * @returns A tuple of [node, value]. */ protected _keyValueNodeOrEntryToNodeAndValue(keyNodeOrEntry: K | BSTNode<K, V> | [K | null | undefined, V | undefined] | null | undefined, value?: V): [OptNode<BSTNode<K, V>>, V | undefined]; /** * (Protected) Sets the root node and clears its parent reference. * @remarks Time O(1) * * @param v - The node to set as root. */ protected _setRoot(v: OptNode<BSTNode<K, V>>): void; /** * (Protected) Compares two keys using the tree's comparator and reverse setting. * @remarks Time O(1) (or O(C) if `specifyComparable` is used). * * @param a - The first key. * @param b - The second key. * @returns A number (1, -1, or 0) representing the comparison. */ protected _compare(a: K, b: K): number; /** * (Private) Deletes a node by its key. * @remarks Standard BST deletion algorithm. Time O(log N), O(N) worst-case. Space O(1). * * @param key - The key of the node to delete. * @returns True if the node was found and deleted, false otherwise. */ private _deleteByKey; }