trie-typed
Version:
Trie, prefix tree
292 lines (291 loc) • 14.8 kB
TypeScript
/**
* data-structure-typed
*
* @author Pablo Zeng
* @copyright Copyright (c) 2022 Pablo Zeng <zrwusa@gmail.com>
* @license MIT License
*/
import { BST, BSTNode } from './bst';
import type { AVLTreeOptions, BinaryTreeDeleteResult, BinaryTreeOptions, BSTNOptKeyOrNode, EntryCallback, IterationType } from '../../types';
import { BSTOptions } from '../../types';
import { IBinaryTree } from '../../interfaces';
/**
* Represents a Node in an AVL (Adelson-Velsky and Landis) Tree.
* It extends a BSTNode and ensures the 'height' property is maintained.
*
* @template K - The type of the key.
* @template V - The type of the value.
*/
export declare class AVLTreeNode<K = any, V = any> extends BSTNode<K, V> {
parent?: AVLTreeNode<K, V>;
/**
* Creates an instance of AVLTreeNode.
* @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?: AVLTreeNode<K, V> | null | undefined;
/**
* Gets the left child of the node.
* @remarks Time O(1), Space O(1)
*
* @returns The left child.
*/
get left(): AVLTreeNode<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: AVLTreeNode<K, V> | null | undefined);
_right?: AVLTreeNode<K, V> | null | undefined;
/**
* Gets the right child of the node.
* @remarks Time O(1), Space O(1)
*
* @returns The right child.
*/
get right(): AVLTreeNode<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: AVLTreeNode<K, V> | null | undefined);
}
/**
* Represents a self-balancing AVL (Adelson-Velsky and Landis) Tree.
* This tree extends BST and performs rotations on add/delete to maintain balance.
*
* @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. Height-Balanced: Each node's left and right subtrees differ in height by no more than one.
* 2. Automatic Rebalancing: AVL trees rebalance themselves automatically during insertions and deletions.
* 3. Rotations for Balancing: Utilizes rotations (single or double) to maintain balance after updates.
* 4. Order Preservation: Maintains the binary search tree property where left child values are less than the parent, and right child values are greater.
* 5. Efficient Lookups: Offers O(log n) search time, where 'n' is the number of nodes, due to its balanced nature.
* 6. Complex Insertions and Deletions: Due to rebalancing, these operations are more complex than in a regular BST.
* 7. Path Length: The path length from the root to any leaf is longer compared to an unbalanced BST, but shorter than a linear chain of nodes.@example
* // Find elements in a range
* // In interval queries, AVL trees, with their strictly balanced structure and lower height, offer better query efficiency, making them ideal for frequent and high-performance interval queries. In contrast, Red-Black trees, with lower update costs, are more suitable for scenarios involving frequent insertions and deletions where the requirements for interval queries are less demanding.
* type Datum = { timestamp: Date; temperature: number };
* // Fixed dataset of CPU temperature readings
* const cpuData: Datum[] = [
* { timestamp: new Date('2024-12-02T00:00:00'), temperature: 55.1 },
* { timestamp: new Date('2024-12-02T00:01:00'), temperature: 56.3 },
* { timestamp: new Date('2024-12-02T00:02:00'), temperature: 54.8 },
* { timestamp: new Date('2024-12-02T00:03:00'), temperature: 57.2 },
* { timestamp: new Date('2024-12-02T00:04:00'), temperature: 58.0 },
* { timestamp: new Date('2024-12-02T00:05:00'), temperature: 59.4 },
* { timestamp: new Date('2024-12-02T00:06:00'), temperature: 60.1 },
* { timestamp: new Date('2024-12-02T00:07:00'), temperature: 61.3 },
* { timestamp: new Date('2024-12-02T00:08:00'), temperature: 62.0 },
* { timestamp: new Date('2024-12-02T00:09:00'), temperature: 63.5 },
* { timestamp: new Date('2024-12-02T00:10:00'), temperature: 64.0 },
* { timestamp: new Date('2024-12-02T00:11:00'), temperature: 62.8 },
* { timestamp: new Date('2024-12-02T00:12:00'), temperature: 61.5 },
* { timestamp: new Date('2024-12-02T00:13:00'), temperature: 60.2 },
* { timestamp: new Date('2024-12-02T00:14:00'), temperature: 59.8 },
* { timestamp: new Date('2024-12-02T00:15:00'), temperature: 58.6 },
* { timestamp: new Date('2024-12-02T00:16:00'), temperature: 57.4 },
* { timestamp: new Date('2024-12-02T00:17:00'), temperature: 56.2 },
* { timestamp: new Date('2024-12-02T00:18:00'), temperature: 55.7 },
* { timestamp: new Date('2024-12-02T00:19:00'), temperature: 54.5 },
* { timestamp: new Date('2024-12-02T00:20:00'), temperature: 53.2 },
* { timestamp: new Date('2024-12-02T00:21:00'), temperature: 52.8 },
* { timestamp: new Date('2024-12-02T00:22:00'), temperature: 51.9 },
* { timestamp: new Date('2024-12-02T00:23:00'), temperature: 50.5 },
* { timestamp: new Date('2024-12-02T00:24:00'), temperature: 49.8 },
* { timestamp: new Date('2024-12-02T00:25:00'), temperature: 48.7 },
* { timestamp: new Date('2024-12-02T00:26:00'), temperature: 47.5 },
* { timestamp: new Date('2024-12-02T00:27:00'), temperature: 46.3 },
* { timestamp: new Date('2024-12-02T00:28:00'), temperature: 45.9 },
* { timestamp: new Date('2024-12-02T00:29:00'), temperature: 45.0 }
* ];
*
* // Create an AVL tree to store CPU temperature data
* const cpuTemperatureTree = new AVLTree<Date, number, Datum>(cpuData, {
* toEntryFn: ({ timestamp, temperature }) => [timestamp, temperature]
* });
*
* // Query a specific time range (e.g., from 00:05 to 00:15)
* const rangeStart = new Date('2024-12-02T00:05:00');
* const rangeEnd = new Date('2024-12-02T00:15:00');
* const rangeResults = cpuTemperatureTree.rangeSearch([rangeStart, rangeEnd], node => ({
* minute: node ? node.key.getMinutes() : 0,
* temperature: cpuTemperatureTree.get(node ? node.key : undefined)
* }));
*
* console.log(rangeResults); // [
* // { minute: 5, temperature: 59.4 },
* // { minute: 6, temperature: 60.1 },
* // { minute: 7, temperature: 61.3 },
* // { minute: 8, temperature: 62 },
* // { minute: 9, temperature: 63.5 },
* // { minute: 10, temperature: 64 },
* // { minute: 11, temperature: 62.8 },
* // { minute: 12, temperature: 61.5 },
* // { minute: 13, temperature: 60.2 },
* // { minute: 14, temperature: 59.8 },
* // { minute: 15, temperature: 58.6 }
* // ]
*/
export declare class AVLTree<K = any, V = any, R extends object = object> extends BST<K, V, R> implements IBinaryTree<K, V, R> {
/**
* Creates an instance of AVLTree.
* @remarks Time O(N log N) (from `addMany` with balanced add). Space O(N).
*
* @param [keysNodesEntriesOrRaws=[]] - An iterable of items to add.
* @param [options] - Configuration options for the AVL tree.
*/
constructor(keysNodesEntriesOrRaws?: Iterable<K | AVLTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined | R>, options?: AVLTreeOptions<K, V, R>);
/**
* (Protected) Creates a new AVL tree node.
* @remarks Time O(1), Space O(1)
*
* @param key - The key for the new node.
* @param [value] - The value for the new node.
* @returns The newly created AVLTreeNode.
*/
_createNode(key: K, value?: V): AVLTreeNode<K, V>;
/**
* Checks if the given item is an `AVLTreeNode` instance.
* @remarks Time O(1), Space O(1)
*
* @param keyNodeOrEntry - The item to check.
* @returns True if it's an AVLTreeNode, false otherwise.
*/
isNode(keyNodeOrEntry: K | AVLTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined): keyNodeOrEntry is AVLTreeNode<K, V>;
/**
* Adds a new node to the AVL tree and balances the tree path.
* @remarks Time O(log N) (O(H) for BST add + O(H) for `_balancePath`). Space O(H) for path/recursion.
*
* @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 | AVLTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined, value?: V): boolean;
/**
* Deletes a node from the AVL tree and re-balances the tree.
* @remarks Time O(log N) (O(H) for BST delete + O(H) for `_balancePath`). Space O(H) for path/recursion.
*
* @param keyNodeOrEntry - The node to delete.
* @returns An array containing deletion results.
*/
delete(keyNodeOrEntry: K | AVLTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined): BinaryTreeDeleteResult<AVLTreeNode<K, V>>[];
/**
* Rebuilds the tree to be perfectly balanced.
* @remarks AVL trees are already height-balanced, but this makes them *perfectly* balanced (minimal height and all leaves at N or N-1).
* 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;
/**
* Creates a new AVLTree by mapping each [key, value] pair.
* @remarks Time O(N log N) (O(N) iteration + O(log M) `add` for each item into the new tree). 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 AVLTree.
* @param [thisArg] - `this` context for the callback.
* @returns A new, mapped AVLTree.
*/
map<MK = K, MV = V, MR extends object = object>(callback: EntryCallback<K, V | undefined, [MK, MV]>, options?: Partial<BinaryTreeOptions<MK, MV, MR>>, thisArg?: unknown): AVLTree<MK, MV, MR>;
/**
* (Protected) Creates a new, empty instance of the same AVLTree constructor.
* @remarks Time O(1)
*
* @template TK, TV, TR - Generic types for the new instance.
* @param [options] - Options for the new tree.
* @returns A new, empty tree.
*/
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 AVLTree constructor, potentially with different generic types.
* @remarks Time O(N log N) (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 tree.
* @param [options] - Options for the new tree.
* @returns A new AVLTree.
*/
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>>): AVLTree<TK, TV, TR>;
/**
* (Protected) Swaps properties of two nodes, including height.
* @remarks Time O(H) (due to `ensureNode`), but O(1) if nodes are passed directly.
*
* @param srcNode - The source node.
* @param destNode - The destination node.
* @returns The `destNode` (now holding `srcNode`'s properties).
*/
protected _swapProperties(srcNode: BSTNOptKeyOrNode<K, AVLTreeNode<K, V>>, destNode: BSTNOptKeyOrNode<K, AVLTreeNode<K, V>>): AVLTreeNode<K, V> | undefined;
/**
* (Protected) Calculates the balance factor (height(right) - height(left)).
* @remarks Time O(1) (assumes heights are stored).
*
* @param node - The node to check.
* @returns The balance factor (positive if right-heavy, negative if left-heavy).
*/
protected _balanceFactor(node: AVLTreeNode<K, V>): number;
/**
* (Protected) Recalculates and updates the height of a node based on its children's heights.
* @remarks Time O(1) (assumes children's heights are correct).
*
* @param node - The node to update.
*/
protected _updateHeight(node: AVLTreeNode<K, V>): void;
/**
* (Protected) Performs a Left-Left (LL) rotation (a single right rotation).
* @remarks Time O(1), Space O(1)
*
* @param A - The unbalanced node (root of the unbalanced subtree).
*/
protected _balanceLL(A: AVLTreeNode<K, V>): void;
/**
* (Protected) Performs a Left-Right (LR) double rotation.
* @remarks Time O(1), Space O(1)
*
* @param A - The unbalanced node (root of the unbalanced subtree).
*/
protected _balanceLR(A: AVLTreeNode<K, V>): void;
/**
* (Protected) Performs a Right-Right (RR) rotation (a single left rotation).
* @remarks Time O(1), Space O(1)
*
* @param A - The unbalanced node (root of the unbalanced subtree).
*/
protected _balanceRR(A: AVLTreeNode<K, V>): void;
/**
* (Protected) Performs a Right-Left (RL) double rotation.
* @remarks Time O(1), Space O(1)
*
* @param A - The unbalanced node (root of the unbalanced subtree).
*/
protected _balanceRL(A: AVLTreeNode<K, V>): void;
/**
* (Protected) Traverses up the tree from the specified node, updating heights and performing rotations as needed.
* @remarks Time O(log N) (O(H)), as it traverses the path to root. Space O(H) for the path array.
*
* @param node - The node to start balancing from (e.g., the newly inserted node or parent of the deleted node).
*/
protected _balancePath(node: K | AVLTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined): void;
/**
* (Protected) Replaces a node, ensuring height is copied.
* @remarks Time O(1)
*
* @param oldNode - The node to be replaced.
* @param newNode - The node to insert.
* @returns The `newNode`.
*/
protected _replaceNode(oldNode: AVLTreeNode<K, V>, newNode: AVLTreeNode<K, V>): AVLTreeNode<K, V>;
}