Splay Tree Data Structures for TypeScript
splaytree-ts is a TypeScript library that provides efficient implementations of Splay Tree data structures, specifically `SplayTreeMap` and `SplayTreeSet`. Splay trees are self-balancing binary search trees with the distinct characteristic that recently accessed elements are more quickly accessible again, offering O(log(n)) amortized time complexity for fundamental operations like insertion, lookup, and removal. The current stable version is 1.0.2. Its key differentiation lies in the splaying heuristic, which optimizes for temporal locality of reference, making it particularly performant for workloads with skewed access patterns. The library supports custom comparison functions and key validation predicates for flexible use with various data types, enhancing its utility beyond simple primitive comparisons.
Common errors
-
TypeError: Cannot read properties of undefined (reading 'compare')
cause An operation was attempted with a key type that the default or supplied `compare` function could not handle, often when passing a complex object without a custom `compare` function.fixProvide a custom `compare` function to the `SplayTreeMap` or `SplayTreeSet` constructor that knows how to compare your specific key objects. -
Elements are not in expected order or some elements are missing after insertion/deletion.
cause The custom `compare` function provided to the Splay Tree constructor is inconsistent, meaning it doesn't correctly define a total order for the keys or violates comparison rules (e.g., `a < b` and `b < a` for distinct `a, b`).fixReview and correct your custom `compare` function to ensure it always returns a consistent negative, positive, or zero value based on the relative order of `a` and `b`. -
TypeError: Cannot read properties of null (reading 'has')
cause A method like `has`, `get`, or `delete` was called with `null`, `undefined`, or a key type not supported by the `compare` function, and no `isValidKey` predicate was provided or it failed to catch the invalid type.fixImplement and supply an `isValidKey` predicate function to the `SplayTreeMap`/`SplayTreeSet` constructor to explicitly validate input key types before comparison, preventing operations with unsupported values.
Warnings
- gotcha Using a custom `compare` function that is inconsistent (e.g., doesn't define a total order or violates transitivity) will lead to an improperly balanced or ordered tree, resulting in incorrect lookup and iteration behavior.
- gotcha Attempting to use `SplayTreeMap` or `SplayTreeSet` with complex object keys without providing a custom `compare` function in the constructor will result in incorrect behavior, as the default comparison assumes natural ordering which is typically only valid for primitives (numbers, strings).
- gotcha The `isValidKey` predicate function is essential when keys might include `null`, `undefined`, or types not directly handled by your `compare` function. Omitting it can lead to `TypeError`s during operations like `get`, `has`, or `delete` if an invalid key type is passed.
- gotcha Modifying a `SplayTreeMap` or `SplayTreeSet` (adding or removing elements) while iterating over it using `forEach` can lead to unpredictable behavior or infinite loops, as the internal structure of the tree changes during iteration.
Install
-
npm install splaytree-ts -
yarn add splaytree-ts -
pnpm add splaytree-ts
Imports
- SplayTreeSet
const SplayTreeSet = require('splaytree-ts').SplayTreeSet;import { SplayTreeSet } from 'splaytree-ts'; - SplayTreeMap
import SplayTreeMap from 'splaytree-ts';
import { SplayTreeMap } from 'splaytree-ts';
Quickstart
import { SplayTreeSet, SplayTreeMap } from 'splaytree-ts';
// Example 1: Using SplayTreeSet for numbers
const ages = new SplayTreeSet<number>();
for (const age of [33, 45, 25, 35, 59, 18, 62]) {
ages.add(age);
}
console.log('Ages in set:', Array.from(ages.values())); // [18, 25, 33, 35, 45, 59, 62]
console.log('First age after 35:', ages.firstAfter(35)); // Expected: 45
console.log('Last age before 33:', ages.lastBefore(33)); // Expected: 25
ages.delete(59); // true
console.log('Has 59 after deletion:', ages.has(59)); // false
// Example 2: Using SplayTreeMap with custom comparison for objects
interface User { id: number; name: string; }
const users = new SplayTreeMap<number, User>(
(a, b) => a - b // Compare by user ID
);
users.set(101, { id: 101, name: 'Alice' });
users.set(50, { id: 50, name: 'Bob' });
users.set(200, { id: 200, name: 'Charlie' });
console.log('User with ID 50:', users.get(50)); // { id: 50, name: 'Bob' }