UNPKG

deque-typed

Version:
425 lines (424 loc) 15.4 kB
/** * data-structure-typed * * @author Pablo Zeng * @copyright Copyright (c) 2022 Pablo Zeng * @license MIT License */ import type { Comparator, TreeMultiMapOptions } from '../../types'; import { Range } from '../../common'; import { RedBlackTreeNode } from './red-black-tree'; /** * Node type used by TreeMultiMap (alias to RedBlackTreeNode for backward compatibility). * * @deprecated Direct node manipulation is discouraged. Use TreeMultiMap methods instead. */ export declare class TreeMultiMapNode<K = any, V = any> extends RedBlackTreeNode<K, V[]> { constructor(key: K, value?: V[]); } /** * TreeMultiMap (ordered MultiMap) key bucket (Array of values). * * Semantics (RFC): * - Bucketed design: each key appears once; duplicates live in the bucket. * - `get(key)` returns a **live** bucket reference. * - Default iteration yields bucket entries: `[K, V[]]`. * - Navigable operations (`first/last/ceiling/...`) return entry tuples like TreeMap. * @example * // players ranked by score with their equipment * type Equipment = { * name: string; // Equipment name * quality: 'legendary' | 'epic' | 'rare' | 'common'; * level: number; * }; * * type Player = { * name: string; * score: number; * equipments: Equipment[]; * }; * * // Mock player data with their scores and equipment * const players: Player[] = [ * { * name: 'DragonSlayer', * score: 8750, * equipments: [ * { name: 'AWM', quality: 'legendary', level: 85 }, * { name: 'Level 3 Helmet', quality: 'epic', level: 80 }, * { name: 'Extended Quickdraw Mag', quality: 'rare', level: 75 }, * { name: 'Compensator', quality: 'epic', level: 78 }, * { name: 'Vertical Grip', quality: 'rare', level: 72 } * ] * }, * { * name: 'ShadowNinja', * score: 7200, * equipments: [ * { name: 'M416', quality: 'epic', level: 75 }, * { name: 'Ghillie Suit', quality: 'rare', level: 70 }, * { name: 'Red Dot Sight', quality: 'common', level: 65 }, * { name: 'Extended QuickDraw Mag', quality: 'rare', level: 68 } * ] * }, * { * name: 'RuneMaster', * score: 9100, * equipments: [ * { name: 'KAR98K', quality: 'legendary', level: 90 }, * { name: 'Level 3 Vest', quality: 'legendary', level: 85 }, * { name: 'Holographic Sight', quality: 'epic', level: 82 }, * { name: 'Suppressor', quality: 'legendary', level: 88 }, * { name: 'Level 3 Backpack', quality: 'epic', level: 80 } * ] * }, * { * name: 'BattleKing', * score: 8500, * equipments: [ * { name: 'AUG', quality: 'epic', level: 82 }, * { name: 'Red Dot Sight', quality: 'rare', level: 75 }, * { name: 'Extended Mag', quality: 'common', level: 70 }, * { name: 'Tactical Stock', quality: 'rare', level: 76 } * ] * }, * { * name: 'SniperElite', * score: 7800, * equipments: [ * { name: 'M24', quality: 'legendary', level: 88 }, * { name: 'Compensator', quality: 'epic', level: 80 }, * { name: 'Scope 8x', quality: 'legendary', level: 85 }, * { name: 'Level 2 Helmet', quality: 'rare', level: 75 } * ] * }, * { * name: 'RushMaster', * score: 7500, * equipments: [ * { name: 'Vector', quality: 'rare', level: 72 }, * { name: 'Level 2 Helmet', quality: 'common', level: 65 }, * { name: 'Quickdraw Mag', quality: 'common', level: 60 }, * { name: 'Laser Sight', quality: 'rare', level: 68 } * ] * }, * { * name: 'GhostWarrior', * score: 8200, * equipments: [ * { name: 'SCAR-L', quality: 'epic', level: 78 }, * { name: 'Extended Quickdraw Mag', quality: 'rare', level: 70 }, * { name: 'Holographic Sight', quality: 'epic', level: 75 }, * { name: 'Suppressor', quality: 'rare', level: 72 }, * { name: 'Vertical Grip', quality: 'common', level: 65 } * ] * }, * { * name: 'DeathDealer', * score: 7300, * equipments: [ * { name: 'SKS', quality: 'epic', level: 76 }, * { name: 'Holographic Sight', quality: 'rare', level: 68 }, * { name: 'Extended Mag', quality: 'common', level: 65 } * ] * }, * { * name: 'StormRider', * score: 8900, * equipments: [ * { name: 'MK14', quality: 'legendary', level: 92 }, * { name: 'Level 3 Backpack', quality: 'legendary', level: 85 }, * { name: 'Scope 8x', quality: 'epic', level: 80 }, * { name: 'Suppressor', quality: 'legendary', level: 88 }, * { name: 'Tactical Stock', quality: 'rare', level: 75 } * ] * }, * { * name: 'CombatLegend', * score: 7600, * equipments: [ * { name: 'UMP45', quality: 'rare', level: 74 }, * { name: 'Level 2 Vest', quality: 'common', level: 67 }, * { name: 'Red Dot Sight', quality: 'common', level: 62 }, * { name: 'Extended Mag', quality: 'rare', level: 70 } * ] * } * ]; * * // Create a TreeMultiMap for player rankings * const playerRankings = new TreeMultiMap<number, Equipment, Player>(players, { * toEntryFn: ({ score, equipments }) => [score, equipments], * isMapMode: false * }); * * const topPlayersEquipments = playerRankings.rangeSearch([8900, 10000], node => playerRankings.get(node.key)); * console.log(topPlayersEquipments); // [ * // [ * // { * // name: 'MK14', * // quality: 'legendary', * // level: 92 * // }, * // { name: 'Level 3 Backpack', quality: 'legendary', level: 85 }, * // { * // name: 'Scope 8x', * // quality: 'epic', * // level: 80 * // }, * // { name: 'Suppressor', quality: 'legendary', level: 88 }, * // { * // name: 'Tactical Stock', * // quality: 'rare', * // level: 75 * // } * // ], * // [ * // { name: 'KAR98K', quality: 'legendary', level: 90 }, * // { * // name: 'Level 3 Vest', * // quality: 'legendary', * // level: 85 * // }, * // { name: 'Holographic Sight', quality: 'epic', level: 82 }, * // { * // name: 'Suppressor', * // quality: 'legendary', * // level: 88 * // }, * // { name: 'Level 3 Backpack', quality: 'epic', level: 80 } * // ] * // ]; */ export declare class TreeMultiMap<K = any, V = any, R = any> implements Iterable<[K, V[]]> { #private; /** * Creates a new TreeMultiMap. * @param keysNodesEntriesOrRaws - Initial entries, or raw elements if `toEntryFn` is provided. * @param options - Configuration options including optional `toEntryFn` to transform raw elements. * @remarks Time O(m log m), Space O(m) where m is the number of initial entries * @example * // Standard usage with entries * const mmap = new TreeMultiMap([['a', ['x', 'y']], ['b', ['z']]]); * * // Using toEntryFn to transform raw objects * const players = [{ score: 100, items: ['sword'] }, { score: 200, items: ['shield', 'bow'] }]; * const mmap = new TreeMultiMap(players, { toEntryFn: p => [p.score, p.items] }); */ constructor(keysNodesEntriesOrRaws?: Iterable<K | [K | null | undefined, V[] | undefined] | null | undefined | R>, options?: TreeMultiMapOptions<K, V[], R>); /** * Validates the key against the default comparator rules. * @remarks Time O(1), Space O(1) */ private _validateKey; /** * Number of distinct keys. * @remarks Time O(1), Space O(1) */ get size(): number; /** * Whether the map is empty. * @remarks Time O(1), Space O(1) */ isEmpty(): boolean; /** * Removes all entries from the map. * @remarks Time O(1), Space O(1) */ clear(): void; /** * Bucket length for a key (missing => 0). * @remarks Time O(log n), Space O(1) */ count(key: K): number; /** * Total number of values across all buckets bucket.length). * @remarks Time O(n), Space O(1) */ get totalSize(): number; /** * Whether the map contains the given key. * @remarks Time O(log n), Space O(1) */ has(key: K): boolean; /** * Live bucket reference (do not auto-delete key if bucket becomes empty via mutation). * @remarks Time O(log n), Space O(1) */ get(key: K): V[] | undefined; /** * Append a single value. * @remarks Time O(log n), Space O(1) */ add(key: K, value: V): boolean; /** * Alias for compatibility with existing TreeMultiMap semantics. * @remarks Time O(log n), Space O(1) for single value; O(log n + m) for bucket append */ set(entry: [K | null | undefined, V[] | undefined] | K | null | undefined, value?: V): boolean; set(key: K, value: V): boolean; /** * Deletes a key and its entire bucket. * @remarks Time O(log n), Space O(1) */ delete(key: K): boolean; /** * Check if a specific value exists in a key's bucket. * @remarks Time O(log n + m), Space O(1) where m is bucket size */ hasEntry(key: K, value: V, eq?: (a: V, b: V) => boolean): boolean; /** * Delete a single occurrence of a value from a key's bucket. * @remarks Time O(log n + m), Space O(1) where m is bucket size */ deleteValue(key: K, value: V, eq?: (a: V, b: V) => boolean): boolean; /** * Delete all occurrences of a value from a key's bucket. * @remarks Time O(log n + m), Space O(1) where m is bucket size */ deleteValues(key: K, value: V, eq?: (a: V, b: V) => boolean): number; /** * Iterates over all entries as [key, bucket] pairs. * @remarks Time O(n), Space O(1) */ [Symbol.iterator](): Iterator<[K, V[]]>; /** * Iterates over all keys. * @remarks Time O(n), Space O(1) */ keys(): IterableIterator<K>; /** * Iterates over all buckets. * @remarks Time O(n), Space O(1) */ values(): IterableIterator<V[]>; /** * Iterates over all entries for a specific key. * @remarks Time O(log n + m), Space O(1) where m is bucket size */ entriesOf(key: K): IterableIterator<[K, V]>; /** * Iterates over all values for a specific key. * @remarks Time O(log n + m), Space O(1) where m is bucket size */ valuesOf(key: K): IterableIterator<V>; /** * Iterates over all [key, value] pairs (flattened from buckets). * @remarks Time O(T), Space O(1) where T is totalSize */ flatEntries(): IterableIterator<[K, V]>; /** * Returns the entry with the smallest key. * @remarks Time O(log n), Space O(1) * @example * const map = new TreeMultiMap([[1, ['a']], [2, ['b']]]); * map.first(); // [1, ['a']] */ first(): [K, V[]] | undefined; /** * Returns the entry with the largest key. * @remarks Time O(log n), Space O(1) * @example * const map = new TreeMultiMap([[1, ['a']], [2, ['b']]]); * map.last(); // [2, ['b']] */ last(): [K, V[]] | undefined; /** * Removes and returns the entry with the smallest key. * @remarks Time O(log n), Space O(1) * @example * const map = new TreeMultiMap([[1, ['a']], [2, ['b']]]); * map.pollFirst(); // [1, ['a']] * map.has(1); // false */ pollFirst(): [K, V[]] | undefined; /** * Removes and returns the entry with the largest key. * @remarks Time O(log n), Space O(1) * @example * const map = new TreeMultiMap([[1, ['a']], [2, ['b']]]); * map.pollLast(); // [2, ['b']] * map.has(2); // false */ pollLast(): [K, V[]] | undefined; /** * Returns the entry with the smallest key >= given key. * @remarks Time O(log n), Space O(1) * @example * const map = new TreeMultiMap([[10, ['a']], [20, ['b']], [30, ['c']]]); * map.ceiling(15); // [20, ['b']] * map.ceiling(20); // [20, ['b']] */ ceiling(key: K): [K, V[]] | undefined; /** * Returns the entry with the largest key <= given key. * @remarks Time O(log n), Space O(1) * @example * const map = new TreeMultiMap([[10, ['a']], [20, ['b']], [30, ['c']]]); * map.floor(25); // [20, ['b']] * map.floor(20); // [20, ['b']] */ floor(key: K): [K, V[]] | undefined; /** * Returns the entry with the smallest key > given key. * @remarks Time O(log n), Space O(1) * @example * const map = new TreeMultiMap([[10, ['a']], [20, ['b']], [30, ['c']]]); * map.higher(10); // [20, ['b']] * map.higher(15); // [20, ['b']] */ higher(key: K): [K, V[]] | undefined; /** * Returns the entry with the largest key < given key. * @remarks Time O(log n), Space O(1) * @example * const map = new TreeMultiMap([[10, ['a']], [20, ['b']], [30, ['c']]]); * map.lower(20); // [10, ['a']] * map.lower(15); // [10, ['a']] */ lower(key: K): [K, V[]] | undefined; /** * Prints the internal tree structure (for debugging). * @remarks Time O(n), Space O(n) */ print(): void; /** * Executes a callback for each entry. * @remarks Time O(n), Space O(1) */ forEach(callback: (value: V[], key: K, map: this) => void): void; /** * Creates a new map with entries that pass the predicate. * @remarks Time O(n), Space O(n) */ filter(predicate: (value: V[], key: K, map: this) => boolean): TreeMultiMap<K, V, R>; /** * Creates a new map by transforming each entry. * @remarks Time O(n log n), Space O(n) */ map<V2>(mapper: (value: V[], key: K, map: this) => [K, V2[]]): TreeMultiMap<K, V2, R>; /** * Reduces all entries to a single value. * @remarks Time O(n), Space O(1) */ reduce<U>(callback: (accumulator: U, value: V[], key: K, map: this) => U, initialValue: U): U; /** * Sets multiple entries at once. * @remarks Time O(m log n), Space O(m) where m is input size */ setMany(keysNodesEntriesOrRaws: Iterable<K | [K | null | undefined, V[] | undefined]>): boolean[]; /** * Searches for entries within a key range. * @remarks Time O(log n + k), Space O(k) where k is result size */ rangeSearch<C extends (node: RedBlackTreeNode<K, V[]>) => unknown>(range: Range<K> | [K, K], callback?: C): ReturnType<C>[]; /** * Creates a shallow clone of this map. * @remarks Time O(n log n), Space O(n) */ clone(): TreeMultiMap<K, V, R>; /** * Expose comparator for advanced usage/testing (read-only). * @remarks Time O(1), Space O(1) */ get comparator(): Comparator<K>; }