deque-typed
Version:
443 lines (442 loc) • 17.9 kB
TypeScript
/**
* data-structure-typed
*
* @author Pablo Zeng
* @copyright Copyright (c) 2022 Pablo Zeng <zrwusa@gmail.com>
* @license MIT License
*/
import type { BinaryTreeDeleteResult, BTNRep, CRUD, EntryCallback, FamilyPosition, NodePredicate, RBTNColor, RedBlackTreeOptions } from '../../types';
import { BST } from './bst';
import { IBinaryTree } from '../../interfaces';
export declare class RedBlackTreeNode<K = any, V = any> {
key: K;
value?: V;
parent?: RedBlackTreeNode<K, V>;
/**
* Create a Red-Black Tree node.
* @remarks Time O(1), Space O(1)
* @param key - Node key.
* @param [value] - Node value (unused in map mode trees).
* @param color - Node color.
*/
constructor(key: K, value?: V, color?: RBTNColor);
_left?: RedBlackTreeNode<K, V> | null | undefined;
/**
* Get the left child pointer.
* @remarks Time O(1), Space O(1)
* @returns Left child node, or null/undefined.
*/
get left(): RedBlackTreeNode<K, V> | null | undefined;
/**
* Set the left child and update its parent pointer.
* @remarks Time O(1), Space O(1)
* @param v - New left node, or null/undefined.
* @returns void
*/
set left(v: RedBlackTreeNode<K, V> | null | undefined);
_right?: RedBlackTreeNode<K, V> | null | undefined;
/**
* Get the right child pointer.
* @remarks Time O(1), Space O(1)
* @returns Right child node, or null/undefined.
*/
get right(): RedBlackTreeNode<K, V> | null | undefined;
/**
* Set the right child and update its parent pointer.
* @remarks Time O(1), Space O(1)
* @param v - New right node, or null/undefined.
* @returns void
*/
set right(v: RedBlackTreeNode<K, V> | null | undefined);
_height: number;
/**
* Gets the height of the node (used in self-balancing trees).
* @remarks Time O(1), Space O(1)
*
* @returns The height.
*/
get height(): number;
/**
* Sets the height of the node.
* @remarks Time O(1), Space O(1)
*
* @param value - The new height.
*/
set height(value: number);
_color: RBTNColor;
/**
* Gets the color of the node (used in Red-Black trees).
* @remarks Time O(1), Space O(1)
*
* @returns The node's color.
*/
get color(): RBTNColor;
/**
* Sets the color of the node.
* @remarks Time O(1), Space O(1)
*
* @param value - The new color.
*/
set color(value: RBTNColor);
_count: number;
/**
* Gets the count of nodes in the subtree rooted at this node (used in order-statistic trees).
* @remarks Time O(1), Space O(1)
*
* @returns The subtree node count.
*/
get count(): number;
/**
* Sets the count of nodes in the subtree.
* @remarks Time O(1), Space O(1)
*
* @param value - The new count.
*/
set count(value: number);
/**
* Gets the position of the node relative to its parent.
* @remarks Time O(1), Space O(1)
*
* @returns The family position (e.g., 'ROOT', 'LEFT', 'RIGHT').
*/
get familyPosition(): FamilyPosition;
}
/**
* Represents a Red-Black Tree (self-balancing BST) supporting map-like mode and stable O(log n) updates.
* @remarks Operation complexity depends on the method; see each method's docs.
* @template K
* @template V
* @template R
* 1. Efficient self-balancing, but not completely balanced. Compared with AVLTree, the addition and deletion efficiency is high, but the query efficiency is slightly lower.
* 2. It is BST itself. Compared with Heap which is not completely ordered, RedBlackTree is completely ordered.
*
* @example
* // basic Red-Black Tree with simple number keys
* // Create a simple Red-Black Tree with numeric keys
* const tree = new RedBlackTree([5, 2, 8, 1, 9]);
*
* tree.print();
* // _2___
* // / \
* // 1 _8_
* // / \
* // 5 9
*
* // Verify the tree maintains sorted order
* console.log([...tree.keys()]); // [1, 2, 5, 8, 9];
*
* // Check size
* console.log(tree.size); // 5;
* @example
* // Red-Black Tree with key-value pairs for lookups
* interface Employee {
* id: number;
* name: string;
* }
*
* // Create tree with employee data
* const employees = new RedBlackTree<number, Employee>([
* [1, { id: 1, name: 'Alice' }],
* [3, { id: 3, name: 'Charlie' }],
* [2, { id: 2, name: 'Bob' }]
* ]);
*
* // Retrieve employee by ID
* const alice = employees.get(1);
* console.log(alice?.name); // 'Alice';
*
* // Verify sorted order by ID
* console.log([...employees.keys()]); // [1, 2, 3];
* @example
* // Red-Black Tree range search for filtering
* interface Product {
* name: string;
* price: number;
* }
*
* const products = new RedBlackTree<number, Product>([
* [10, { name: 'Item A', price: 10 }],
* [25, { name: 'Item B', price: 25 }],
* [40, { name: 'Item C', price: 40 }],
* [50, { name: 'Item D', price: 50 }]
* ]);
*
* // Find products in price range [20, 45]
* const pricesInRange = products.rangeSearch([20, 45], node => {
* return products.get(node)?.name;
* });
*
* console.log(pricesInRange); // ['Item B', 'Item C'];
* @example
* // Red-Black Tree as database index for stock market data
* interface StockPrice {
* symbol: string;
* volume: number;
* timestamp: Date;
* }
*
* // Simulate real-time stock price index
* const priceIndex = new RedBlackTree<number, StockPrice>([
* [142.5, { symbol: 'AAPL', volume: 1000000, timestamp: new Date() }],
* [335.2, { symbol: 'MSFT', volume: 800000, timestamp: new Date() }],
* [3285.04, { symbol: 'AMZN', volume: 500000, timestamp: new Date() }],
* [267.98, { symbol: 'META', volume: 750000, timestamp: new Date() }],
* [234.57, { symbol: 'GOOGL', volume: 900000, timestamp: new Date() }]
* ]);
*
* // Find highest-priced stock
* const maxPrice = priceIndex.getRightMost();
* console.log(priceIndex.get(maxPrice)?.symbol); // 'AMZN';
*
* // Find stocks in price range [200, 400] for portfolio balancing
* const stocksInRange = priceIndex.rangeSearch([200, 400], node => {
* const stock = priceIndex.get(node);
* return {
* symbol: stock?.symbol,
* price: node,
* volume: stock?.volume
* };
* });
*
* console.log(stocksInRange.length); // 3;
* console.log(stocksInRange.some((s: any) => s.symbol === 'GOOGL')); // true;
* console.log(stocksInRange.some((s: any) => s.symbol === 'META')); // true;
* console.log(stocksInRange.some((s: any) => s.symbol === 'MSFT')); // true;
*/
export declare class RedBlackTree<K = any, V = any, R = any> extends BST<K, V, R> implements IBinaryTree<K, V, R> {
constructor(keysNodesEntriesOrRaws?: Iterable<K | RedBlackTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined | R>, options?: RedBlackTreeOptions<K, V, R>);
protected _root: RedBlackTreeNode<K, V> | undefined;
/**
* (Internal) Header sentinel:
* - header.parent -> root
* - header._left -> min (or NIL)
* - header._right -> max (or NIL)
*
* IMPORTANT:
* - This header is NOT part of the actual tree.
* - Do NOT use `header.left` / `header.right` accessors for wiring: those setters update `NIL.parent`
* and can corrupt sentinel invariants / cause hangs. Only touch `header._left/_right`.
*/
protected _header: RedBlackTreeNode<K, V>;
/**
* (Internal) Cache of the current minimum and maximum nodes.
* Used for fast-path insert/update when keys are monotonic or near-boundary.
*/
protected _minNode: RedBlackTreeNode<K, V> | undefined;
protected _maxNode: RedBlackTreeNode<K, V> | undefined;
/**
* Get the current root node.
* @remarks Time O(1), Space O(1)
* @returns Root node, or undefined.
*/
get root(): RedBlackTreeNode<K, V> | undefined;
/**
* Create a red-black node for the given key/value (value ignored in map mode).
* @remarks Time O(1), Space O(1)
* @param key - See parameter type for details.
* @param [value] - See parameter type for details.
* @param color - See parameter type for details.
* @returns A new RedBlackTreeNode instance.
*/
createNode(key: K, value?: V, color?: RBTNColor): RedBlackTreeNode<K, V>;
/**
* Type guard: check whether the input is a RedBlackTreeNode.
* @remarks Time O(1), Space O(1)
* @param keyNodeOrEntry - See parameter type for details.
* @returns True if the value is a RedBlackTreeNode.
*/
isNode(keyNodeOrEntry: K | RedBlackTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined): keyNodeOrEntry is RedBlackTreeNode<K, V>;
/**
* Remove all nodes and clear the key→value store (if in map mode).
* @remarks Time O(n), Space O(1)
* @returns void
*/
/**
* Remove all nodes and clear internal caches.
* @remarks Time O(n) average, Space O(1)
*/
clear(): void;
/**
* (Internal) Find a node by key using a tight BST walk (no allocations).
*
* NOTE: This uses `header.parent` as the canonical root pointer.
* @remarks Time O(log n) average, Space O(1)
*/
protected _findNodeByKey(key: K): RedBlackTreeNode<K, V> | undefined;
/**
* (Internal) In-order predecessor of a node in a BST.
* @remarks Time O(log n) average, Space O(1)
*/
protected _predecessorOf(node: RedBlackTreeNode<K, V>): RedBlackTreeNode<K, V> | undefined;
/**
* (Internal) In-order successor of a node in a BST.
* @remarks Time O(log n) average, Space O(1)
*/
protected _successorOf(node: RedBlackTreeNode<K, V>): RedBlackTreeNode<K, V> | undefined;
/**
* (Internal) Attach a new node directly under a known parent/side (no search).
*
* This is a performance-oriented helper used by boundary fast paths and hinted insertion.
* It will:
* - wire parent/child pointers (using accessors, so parent pointers are updated)
* - initialize children to NIL
* - mark the new node RED, then run insert fix-up
*
* Precondition: the chosen slot (parent.left/parent.right) is empty (NIL/null/undefined).
* @remarks Time O(log n) average, Space O(1)
*/
protected _attachNewNode(parent: RedBlackTreeNode<K, V>, side: 'left' | 'right', node: RedBlackTreeNode<K, V>): void;
/**
* (Internal) a single source of truth for min/max is header._left/_right.
* Keep legacy _minNode/_maxNode mirrored for compatibility.
* @remarks Time O(1), Space O(1)
*/
/**
* (Internal) Update min cache pointers (header._left is the canonical min pointer).
* @remarks Time O(1), Space O(1)
*/
protected _setMinCache(node: RedBlackTreeNode<K, V> | undefined): void;
/**
* (Internal) Update max cache pointers (header._right is the canonical max pointer).
* @remarks Time O(1), Space O(1)
*/
protected _setMaxCache(node: RedBlackTreeNode<K, V> | undefined): void;
/**
* (Internal) Core set implementation returning the affected node.
*
* Hot path goals:
* - Avoid double walks (search+insert): do a single traversal that either updates or inserts.
* - Use header min/max caches to fast-path boundary inserts.
* - Keep header._left/_right as canonical min/max pointers.
*
* Return value:
* - `{ node, created:false }` when an existing key is updated
* - `{ node, created:true }` when a new node is inserted
* - `undefined` only on unexpected internal failure.
* @remarks Time O(log n) average, Space O(1)
*/
protected _setKVNode(key: K, nextValue?: V): {
node: RedBlackTreeNode<K, V>;
created: boolean;
} | undefined;
/**
* (Internal) Boolean wrapper around `_setKVNode`.
*
* Includes a map-mode update fast-path:
* - If `isMapMode=true` and the key already exists in `_store`, then updating the value does not
* require any tree search/rotation (tree shape depends only on key).
* - This path is intentionally limited to `nextValue !== undefined` to preserve existing
* semantics for `undefined` values.
* @remarks Time O(log n) average, Space O(1)
*/
protected _setKV(key: K, nextValue?: V): boolean;
/**
* Insert/update using a hint node to speed up nearby insertions.
*
* close to the expected insertion position (often the previously returned node in a loop).
*
* When the hint is a good fit (sorted / nearly-sorted insertion), this can avoid most of the
* normal root-to-leaf search and reduce constant factors.
*
* When the hint does not match (random workloads), this will fall back to the normal set path.
* @remarks Time O(log n) average, Space O(1)
*/
setWithHintNode(key: K, value: V, hint?: RedBlackTreeNode<K, V>): RedBlackTreeNode<K, V> | undefined;
/**
* Boolean wrapper for setWithHintNode.
* @remarks Time O(log n) average, Space O(1)
*/
setWithHint(key: K, value: V, hint?: RedBlackTreeNode<K, V>): boolean;
/**
* Insert or update a key/value (map mode) or key-only (set mode).
*
* This method is optimized for:
* - monotonic inserts via min/max boundary fast paths
* - updates via a single-pass search (no double walk)
*
* @remarks Time O(log n) average, Space O(1)
*/
set(keyNodeOrEntry: K | RedBlackTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined, value?: V): boolean;
/**
* Delete a node by key/node/entry and rebalance as needed.
* @remarks Time O(log n) average, Space O(1)
* @param keyNodeEntryRawOrPredicate - Key, node, or [key, value] entry identifying the node to delete.
* @returns Array with deletion metadata (removed node, rebalancing hint if any).
*/
delete(keyNodeEntryRawOrPredicate: BTNRep<K, V, RedBlackTreeNode<K, V>> | NodePredicate<RedBlackTreeNode<K, V> | null>): BinaryTreeDeleteResult<RedBlackTreeNode<K, V>>[];
/**
* Transform entries into a like-kind red-black tree with possibly different key/value types.
* @remarks Time O(n) average, Space O(n)
* @template MK
* @template MV
* @template MR
* @param callback - Mapping function from (key, value, index, tree) to a new [key, value].
* @param [options] - See parameter type for details.
* @param [thisArg] - See parameter type for details.
* @returns A new RedBlackTree with mapped entries.
*/
map<MK = K, MV = V, MR = any>(callback: EntryCallback<K, V | undefined, [MK, MV]>, options?: Partial<RedBlackTreeOptions<MK, MV, MR>>, thisArg?: unknown): RedBlackTree<MK, MV, MR>;
/**
* (Internal) Create an empty instance of the same concrete tree type.
* @remarks Time O(1) average, Space O(1)
*/
protected _createInstance<TK = K, TV = V, TR = R>(options?: Partial<RedBlackTreeOptions<TK, TV, TR>>): this;
/**
* (Internal) Create a like-kind tree (same concrete class) populated from an iterable.
* @remarks Time O(m log m) average (m = iterable length), Space O(m)
*/
protected _createLike<TK = K, TV = V, TR = R>(iter?: Iterable<TK | RedBlackTreeNode<TK, TV> | [TK | null | undefined, TV | undefined] | null | undefined | TR>, options?: Partial<RedBlackTreeOptions<TK, TV, TR>>): RedBlackTree<TK, TV, TR>;
/**
* (Internal) Set the root pointer and keep header.parent in sync.
* @remarks Time O(1), Space O(1)
*/
protected _setRoot(v: RedBlackTreeNode<K, V> | undefined): void;
/**
* (Internal) Replace a node in place while preserving its color.
* @remarks Time O(1) average, Space O(1)
*/
protected _replaceNode(oldNode: RedBlackTreeNode<K, V>, newNode: RedBlackTreeNode<K, V>): RedBlackTreeNode<K, V>;
/**
* (Protected) Standard BST insert followed by red-black fix-up.
* @remarks Time O(log n) average, Space O(1)
* @param node - Node to insert.
* @returns Status string: 'CREATED' or 'UPDATED'.
*/
protected _insert(node: RedBlackTreeNode<K, V>): CRUD;
/**
* (Protected) Transplant a subtree in place of another during deletion.
* @remarks Time O(1), Space O(1)
* @param u - Node to replace.
* @param v - Replacement subtree root (may be undefined).
* @returns void
*/
protected _transplant(u: RedBlackTreeNode<K, V>, v: RedBlackTreeNode<K, V> | undefined): void;
/**
* (Protected) Restore red-black properties after insertion (recolor/rotate).
* @remarks Time O(log n) average, Space O(1)
* @param z - Recently inserted node.
* @returns void
*/
protected _insertFixup(z: RedBlackTreeNode<K, V> | undefined): void;
/**
* (Protected) Restore red-black properties after deletion (recolor/rotate).
* @remarks Time O(log n) average, Space O(1)
* @param node - Child that replaced the deleted node (may be undefined).
* @returns void
*/
protected _deleteFixup(node: RedBlackTreeNode<K, V> | undefined): void;
/**
* (Protected) Perform a left rotation around x.
* @remarks Time O(1), Space O(1)
* @param x - Pivot node to rotate around.
* @returns void
*/
protected _leftRotate(x: RedBlackTreeNode<K, V> | undefined): void;
/**
* (Protected) Perform a right rotation around y.
* @remarks Time O(1), Space O(1)
* @param y - Pivot node to rotate around.
* @returns void
*/
protected _rightRotate(y: RedBlackTreeNode<K, V> | undefined): void;
}