/** * TreeSet (ordered set) — a restricted, native-like API backed by RedBlackTree. * * Design goals: * - No node exposure (no node inputs/outputs) * - Native Set-like surface + Java NavigableSet-like helpers * - Strict default comparator (number/string/Date), otherwise require comparator */ import type { Comparator } from '../../types'; import type { TreeSetElementCallback, TreeSetOptions, TreeSetRangeOptions, TreeSetReduceCallback } from '../../types'; /** * An ordered Set backed by a red-black tree. * * - Iteration order is ascending by key. * - No node exposure: all APIs use keys only. * @example * // Set multiple key-value pairs * const ts = new TreeSet(); * ts.setMany([[1, 'a'], [2, 'b'], [3, 'c']]); * console.log(ts.size); // 3; */ export declare class TreeSet implements Iterable { #private; /** * Create a TreeSet from an iterable of keys or raw elements. * * @param elements - Iterable of keys, or raw elements if `toElementFn` is provided. * @param options - Configuration options including optional `toElementFn` to transform raw elements. * @throws {TypeError} When using the default comparator and encountering unsupported key types, * or invalid keys (e.g. `NaN`, invalid `Date`). * @example * // Standard usage with keys * const set = new TreeSet([3, 1, 2]); * * // Using toElementFn to transform raw objects * const users = [{ id: 3, name: 'Alice' }, { id: 1, name: 'Bob' }]; * const set = new TreeSet(users, { toElementFn: u => u.id }); */ constructor(elements?: Iterable | Iterable, options?: TreeSetOptions); /** * Create the strict default comparator. * * Supports: * - `number` (rejects `NaN`; treats `-0` and `0` as equal) * - `string` * - `Date` (orders by `getTime()`, rejects invalid dates) * * For other key types, a custom comparator must be provided. */ static createDefaultComparator(): Comparator; /** * Number of elements in the set. */ get size(): number; /** * Whether the set is empty. * @example * // Check empty * console.log(new TreeSet().isEmpty()); // true; */ isEmpty(): boolean; private _validateKey; /** * Add a key to the set (no-op if already present). * @remarks Expected time O(log n) * @example * // Unique tags with sorted order * const tags = new TreeSet(['javascript', 'typescript', 'react', 'typescript', 'node']); * * // Duplicates removed, sorted alphabetically * console.log([...tags]); // ['javascript', 'node', 'react', 'typescript']; * console.log(tags.size); // 4; * * tags.add('angular'); * console.log(tags.first()); // 'angular'; * console.log(tags.last()); // 'typescript'; */ add(key: K): this; /** * Add multiple keys at once. * @remarks Expected time O(m log n), where m is the number of keys. * @param keys - Iterable of keys to add. * @returns Array of booleans indicating whether each key was newly added. * @example * // Add multiple keys * const ts = new TreeSet(); * ts.addMany([5, 3, 7, 1, 9]); * console.log(ts.size); // 5; */ addMany(keys: Iterable): boolean[]; /** * Test whether a key exists. * @remarks Expected time O(log n) * @example * // Checking membership in a sorted collection * const allowed = new TreeSet(['admin', 'editor', 'viewer']); * * console.log(allowed.has('admin')); // true; * console.log(allowed.has('guest')); // false; */ has(key: K): boolean; /** * Delete a key. * @returns `true` if the key existed; otherwise `false`. * @remarks Expected time O(log n) * @example * // Removing elements while maintaining order * const nums = new TreeSet([1, 3, 5, 7, 9]); * * console.log(nums.delete(5)); // true; * console.log(nums.delete(5)); // false; // already gone * console.log([...nums]); // [1, 3, 7, 9]; */ delete(key: K): boolean; /** * Delete all keys matching a predicate. * @remarks Time O(N), Space O(N) * @param predicate - Function (key, index, set) → boolean; return true to delete. * @returns True if at least one key was deleted. */ deleteWhere(predicate: (key: K, index: number, set: this) => boolean): boolean; /** * Remove all keys. * @example * // Remove all * const ts = new TreeSet([1, 2]); * ts.clear(); * console.log(ts.isEmpty()); // true; */ clear(): void; /** * Iterate over keys in ascending order. * @example * // Get sorted keys * const ts = new TreeSet([30, 10, 20]); * console.log([...ts.keys()]); // [10, 20, 30]; */ keys(): IterableIterator; /** * Iterate over values in ascending order. * * Note: for Set-like containers, `values()` is the same as `keys()`. * @example * // Get values (same as keys for Set) * const ts = new TreeSet([2, 1, 3]); * console.log([...ts.values()]); // [1, 2, 3]; */ values(): IterableIterator; /** * Iterate over `[value, value]` pairs (native Set convention). * * Note: TreeSet stores only keys internally; `[k, k]` is created on-the-fly during iteration. * @example * // Iterate entries * const ts = new TreeSet([3, 1, 2]); * console.log([...ts.entries()].map(([k]) => k)); // [1, 2, 3]; */ entries(): IterableIterator<[K, K]>; [Symbol.iterator](): IterableIterator; /** * Visit each value in ascending order. * * Callback follows native Set convention: `(value, value2, set)`. * @example * // Execute for each * const ts = new TreeSet([3, 1, 2]); * const keys: number[] = []; * ts.forEach(k => keys.push(k)); * console.log(keys); // [1, 2, 3]; */ forEach(cb: (value: K, value2: K, set: TreeSet) => void, thisArg?: unknown): void; /** * Create a new TreeSet by mapping each value to a new key. * * This mirrors `RedBlackTree.map`: mapping produces a new ordered container. * @remarks Time O(n log n) expected, Space O(n) * @example * // Transform * const ts = new TreeSet([1, 2, 3]); * const doubled = ts.map(k => k * 2); * console.log([...doubled]); // [2, 4, 6]; */ map(callbackfn: TreeSetElementCallback>, options?: Omit, 'toElementFn'> & { comparator?: (a: MK, b: MK) => number; }, thisArg?: unknown): TreeSet; /** * Create a new TreeSet containing only values that satisfy the predicate. * @remarks Time O(n log n) expected, Space O(n) * @example * // Filter * const ts = new TreeSet([1, 2, 3, 4, 5]); * const evens = ts.filter(k => k % 2 === 0); * console.log([...evens]); // [2, 4]; */ filter(callbackfn: TreeSetElementCallback>, thisArg?: unknown): TreeSet; /** * Reduce values into a single accumulator. * @remarks Time O(n), Space O(1) * @example * // Aggregate * const ts = new TreeSet([1, 2, 3]); * const sum = ts.reduce((acc, k) => acc + k, 0); * console.log(sum); // 6; */ reduce(callbackfn: TreeSetReduceCallback>, initialValue: A): A; /** * Test whether all values satisfy a predicate. * @remarks Time O(n), Space O(1) * @example * // Test all * const ts = new TreeSet([2, 4, 6]); * console.log(ts.every(k => k > 0)); // true; */ every(callbackfn: TreeSetElementCallback>, thisArg?: unknown): boolean; /** * Test whether any value satisfies a predicate. * @remarks Time O(n), Space O(1) * @example * // Test any * const ts = new TreeSet([1, 3, 5]); * console.log(ts.some(k => k === 3)); // true; */ some(callbackfn: TreeSetElementCallback>, thisArg?: unknown): boolean; /** * Find the first value that satisfies a predicate. * @remarks Time O(n), Space O(1) * @example * // Find entry * const ts = new TreeSet([1, 2, 3]); * const found = ts.find(k => k === 2); * console.log(found); // 2; */ find(callbackfn: TreeSetElementCallback>, thisArg?: unknown): K | undefined; /** * Materialize the set into an array of keys. * @remarks Time O(n), Space O(n) * @example * // Convert to array * const ts = new TreeSet([3, 1, 2]); * console.log(ts.toArray()); // [1, 2, 3]; */ toArray(): K[]; /** * Print a human-friendly representation. * @remarks Time O(n), Space O(n) * @example * // Display tree * const ts = new TreeSet([1, 2, 3]); * expect(() => ts.print()).not.toThrow(); */ print(): void; /** * Smallest key in the set. * @example * // Student grade ranking with custom comparator * interface Student { * name: string; * gpa: number; * } * * const ranking = new TreeSet( * [ * { name: 'Alice', gpa: 3.8 }, * { name: 'Bob', gpa: 3.5 }, * { name: 'Charlie', gpa: 3.9 }, * { name: 'Diana', gpa: 3.5 } * ], * { comparator: (a, b) => b.gpa - a.gpa || a.name.localeCompare(b.name) } * ); * * // Sorted by GPA descending, then name ascending * const names = [...ranking].map(s => s.name); * console.log(names); // ['Charlie', 'Alice', 'Bob', 'Diana']; * * // Top student * console.log(ranking.first()?.name); // 'Charlie'; * * // Filter students with GPA >= 3.8 * const honors = ranking.filter(s => s.gpa >= 3.8); * console.log(honors.toArray().map(s => s.name)); // ['Charlie', 'Alice']; */ first(): K | undefined; /** * Largest key in the set. * @example * // Get the maximum element * const temps = new TreeSet([18, 22, 15, 30, 25]); * console.log(temps.last()); // 30; * console.log(temps.first()); // 15; */ last(): K | undefined; /** * Remove and return the smallest key. * @example * // Remove and return minimum * const queue = new TreeSet([5, 1, 8, 3]); * * console.log(queue.pollFirst()); // 1; * console.log(queue.pollFirst()); // 3; * console.log(queue.size); // 2; */ pollFirst(): K | undefined; /** * Remove and return the largest key. * @example * // Remove and return maximum * const stack = new TreeSet([10, 20, 30]); * * console.log(stack.pollLast()); // 30; * console.log(stack.size); // 2; */ pollLast(): K | undefined; /** * Smallest key that is >= the given key. * @example * // Finding nearest available time slot * // Available appointment times (minutes from midnight) * const slots = new TreeSet([540, 600, 660, 720, 840, 900]); * * // Customer wants something around 10:30 (630 min) * const nearest = slots.ceiling(630); * console.log(nearest); // 660; // 11:00 AM * * // What's the latest slot before 2:00 PM (840)? * const before2pm = slots.lower(840); * console.log(before2pm); // 720; // 12:00 PM * * // Book the 11:00 slot * slots.delete(660); * console.log(slots.ceiling(630)); // 720; */ ceiling(key: K): K | undefined; /** * Largest key that is <= the given key. * @example * // Largest element ≤ target * const breakpoints = new TreeSet([320, 768, 1024, 1280, 1920]); * * // Current width is 800 → which breakpoint applies? * console.log(breakpoints.floor(800)); // 768; * console.log(breakpoints.floor(1024)); // 1024; // exact match * console.log(breakpoints.floor(100)); // undefined; */ floor(key: K): K | undefined; /** * Smallest key that is > the given key. * @example * // Smallest element strictly > target * const levels = new TreeSet([1, 5, 10, 25, 50, 100]); * * console.log(levels.higher(10)); // 25; * console.log(levels.higher(100)); // undefined; */ higher(key: K): K | undefined; /** * Largest key that is < the given key. * @example * // Largest element strictly < target * const tiers = new TreeSet([100, 200, 500, 1000]); * * console.log(tiers.lower(500)); // 200; * console.log(tiers.lower(100)); // undefined; */ lower(key: K): K | undefined; /** * Return all keys in a given range. * * @param range `[low, high]` * @param options Inclusive/exclusive bounds (defaults to inclusive). * @example * // IP address blocklist with range checking * // Simplified: use numeric IP representation * const blocklist = new TreeSet([ * 167772160, // 10.0.0.0 * 167772416, // 10.0.1.0 * 167772672, // 10.0.2.0 * 167773184 // 10.0.4.0 * ]); * * // Check if any blocked IP is in range 10.0.1.0 - 10.0.3.0 * const inRange = blocklist.rangeSearch([167772416, 167772928]); * console.log(inRange); // [167772416, 167772672]; * * // Quick membership check * console.log(blocklist.has(167772416)); // true; * console.log(blocklist.has(167772800)); // false; */ rangeSearch(range: [K, K], options?: TreeSetRangeOptions): K[]; /** * Returns the element at the k-th position in tree order (0-indexed). * @remarks Time O(log n). Requires `enableOrderStatistic: true`. * @example * // Find k-th element in a TreeSet * const set = new TreeSet([30, 10, 50, 20, 40], { enableOrderStatistic: true }); * console.log(set.getByRank(0)); // 10; * console.log(set.getByRank(2)); // 30; * console.log(set.getRank(30)); // 2; */ getByRank(k: number): K | undefined; /** * Returns the 0-based rank of a key (number of elements that precede it in tree order). * @remarks Time O(log n). Requires `enableOrderStatistic: true`. * @example * // Get the rank of a key in sorted order * const tree = new TreeSet( * [10, 20, 30, 40, 50], * { enableOrderStatistic: true } * ); * console.log(tree.getRank(10)); // 0; // smallest → rank 0 * console.log(tree.getRank(30)); // 2; // 2 elements before 30 in tree order * console.log(tree.getRank(50)); // 4; // largest → rank 4 * console.log(tree.getRank(25)); // 2; */ getRank(key: K): number; /** * Returns elements by rank range (0-indexed, inclusive on both ends). * @remarks Time O(log n + k). Requires `enableOrderStatistic: true`. * @example * // Pagination by position in tree order * const tree = new TreeSet( * [10, 20, 30, 40, 50, 60, 70, 80, 90], * { enableOrderStatistic: true } * ); * const pageSize = 3; * * // Page 1 * console.log(tree.rangeByRank(0, pageSize - 1)); // [10, 20, 30]; * // Page 2 * console.log(tree.rangeByRank(pageSize, 2 * pageSize - 1)); // [40, 50, 60]; * // Page 3 * console.log(tree.rangeByRank(2 * pageSize, 3 * pageSize - 1)); // [70, 80, 90]; */ rangeByRank(start: number, end: number): K[]; /** * Creates a shallow clone of this set. * @remarks Time O(n log n), Space O(n) * @example * // Deep clone * const ts = new TreeSet([1, 2, 3]); * const copy = ts.clone(); * copy.delete(1); * console.log(ts.has(1)); // true; */ /** * Return a new TreeSet containing all elements from both sets. * @remarks When both sets share the same comparator, uses O(n+m) merge. Otherwise O(m log n). * @param other - Any iterable of keys. * @returns A new TreeSet. * @example * // Merge two sets * console.log([...a.union(b)]); // [1, 2, 3, 4, 5, 6, 7]; */ union(other: Iterable): TreeSet; /** * Return a new TreeSet containing only elements present in both sets. * @remarks Time O(n+m) with ordered merge when possible, otherwise O(n log m). * @param other - Any iterable of keys (converted to Set for fast lookup if not a TreeSet). * @returns A new TreeSet. * @example * // Find common elements * console.log([...a.intersection(b)]); // [3, 4, 5]; */ intersection(other: Iterable): TreeSet; /** * Return a new TreeSet containing elements in this set but not in the other. * @remarks Time O(n+m) with ordered merge when possible, otherwise O(n log m). * @param other - Any iterable of keys. * @returns A new TreeSet. * @example * // Find exclusive elements * console.log([...a.difference(b)]); // [1, 2]; */ difference(other: Iterable): TreeSet; /** * Return a new TreeSet containing elements in either set but not both. * @remarks Time O(n+m). * @param other - Any iterable of keys. * @returns A new TreeSet. * @example * // Find symmetric difference * console.log([...a.symmetricDifference(b)]); // [1, 2, 6, 7]; */ symmetricDifference(other: Iterable): TreeSet; /** * Check whether every element in this set is also in the other. * @remarks Time O(n). * @param other - Any iterable of keys (converted to Set for fast lookup if not a TreeSet). * @returns `true` if this is a subset of other. * @example * // Check subset * console.log(new TreeSet([3, 4]).isSubsetOf(a)); // true; */ isSubsetOf(other: Iterable): boolean; /** * Check whether every element in the other set is also in this set. * @remarks Time O(m). * @param other - Any iterable of keys. * @returns `true` if this is a superset of other. * @example * // Check superset * console.log(a.isSupersetOf(new TreeSet([2, 3]))); // true; */ isSupersetOf(other: Iterable): boolean; /** * Check whether this set and the other share no common elements. * @remarks Time O(min(n,m)), can short-circuit on first overlap. * @param other - Any iterable of keys (converted to Set for fast lookup if not a TreeSet). * @returns `true` if sets are disjoint. * @example * // Check disjoint * console.log(a.isDisjointFrom(new TreeSet([8, 9]))); // true; */ isDisjointFrom(other: Iterable): boolean; /** * Deep copy * @example * // Deep clone * const ts = new TreeSet([1, 2, 3]); * const copy = ts.clone(); * copy.delete(1); * console.log(ts.has(1)); // true; */ clone(): TreeSet; }