data-structure-typed 2.5.1 → 2.5.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +5 -1
- package/MIGRATION.md +169 -0
- package/README.md +135 -23
- package/README_CN.md +551 -143
- package/SPECIFICATION.md +20 -14
- package/SPECIFICATION.zh-CN.md +20 -14
- package/dist/cjs/binary-tree.cjs +6460 -1591
- package/dist/cjs/graph.cjs +440 -20
- package/dist/cjs/hash.cjs +125 -22
- package/dist/cjs/heap.cjs +196 -47
- package/dist/cjs/index.cjs +8486 -2429
- package/dist/cjs/linked-list.cjs +456 -31
- package/dist/cjs/matrix.cjs +79 -9
- package/dist/cjs/priority-queue.cjs +193 -44
- package/dist/cjs/queue.cjs +391 -2
- package/dist/cjs/stack.cjs +92 -6
- package/dist/cjs/trie.cjs +122 -28
- package/dist/cjs-legacy/binary-tree.cjs +6484 -1612
- package/dist/cjs-legacy/graph.cjs +440 -20
- package/dist/cjs-legacy/hash.cjs +125 -22
- package/dist/cjs-legacy/heap.cjs +196 -47
- package/dist/cjs-legacy/index.cjs +8654 -2594
- package/dist/cjs-legacy/linked-list.cjs +456 -31
- package/dist/cjs-legacy/matrix.cjs +79 -9
- package/dist/cjs-legacy/priority-queue.cjs +193 -44
- package/dist/cjs-legacy/queue.cjs +391 -2
- package/dist/cjs-legacy/stack.cjs +92 -6
- package/dist/cjs-legacy/trie.cjs +122 -28
- package/dist/esm/binary-tree.mjs +6460 -1591
- package/dist/esm/graph.mjs +440 -20
- package/dist/esm/hash.mjs +125 -22
- package/dist/esm/heap.mjs +196 -47
- package/dist/esm/index.mjs +8486 -2430
- package/dist/esm/linked-list.mjs +456 -31
- package/dist/esm/matrix.mjs +79 -9
- package/dist/esm/priority-queue.mjs +193 -44
- package/dist/esm/queue.mjs +391 -2
- package/dist/esm/stack.mjs +92 -6
- package/dist/esm/trie.mjs +122 -28
- package/dist/esm-legacy/binary-tree.mjs +6484 -1612
- package/dist/esm-legacy/graph.mjs +440 -20
- package/dist/esm-legacy/hash.mjs +125 -22
- package/dist/esm-legacy/heap.mjs +196 -47
- package/dist/esm-legacy/index.mjs +8654 -2595
- package/dist/esm-legacy/linked-list.mjs +456 -31
- package/dist/esm-legacy/matrix.mjs +79 -9
- package/dist/esm-legacy/priority-queue.mjs +193 -44
- package/dist/esm-legacy/queue.mjs +391 -2
- package/dist/esm-legacy/stack.mjs +92 -6
- package/dist/esm-legacy/trie.mjs +122 -28
- package/dist/types/common/error.d.ts +9 -0
- package/dist/types/common/index.d.ts +1 -1
- package/dist/types/data-structures/binary-tree/avl-tree.d.ts +98 -2
- package/dist/types/data-structures/binary-tree/binary-indexed-tree.d.ts +112 -0
- package/dist/types/data-structures/binary-tree/binary-tree.d.ts +214 -13
- package/dist/types/data-structures/binary-tree/bst.d.ts +294 -3
- package/dist/types/data-structures/binary-tree/red-black-tree.d.ts +155 -8
- package/dist/types/data-structures/binary-tree/segment-tree.d.ts +48 -0
- package/dist/types/data-structures/binary-tree/tree-map.d.ts +1370 -323
- package/dist/types/data-structures/binary-tree/tree-multi-map.d.ts +1329 -316
- package/dist/types/data-structures/binary-tree/tree-multi-set.d.ts +1116 -295
- package/dist/types/data-structures/binary-tree/tree-set.d.ts +1330 -326
- package/dist/types/data-structures/graph/directed-graph.d.ts +80 -0
- package/dist/types/data-structures/graph/undirected-graph.d.ts +72 -0
- package/dist/types/data-structures/hash/hash-map.d.ts +95 -6
- package/dist/types/data-structures/heap/heap.d.ts +154 -12
- package/dist/types/data-structures/linked-list/doubly-linked-list.d.ts +143 -0
- package/dist/types/data-structures/linked-list/singly-linked-list.d.ts +121 -1
- package/dist/types/data-structures/linked-list/skip-linked-list.d.ts +144 -0
- package/dist/types/data-structures/matrix/matrix.d.ts +64 -0
- package/dist/types/data-structures/queue/deque.d.ts +142 -0
- package/dist/types/data-structures/queue/queue.d.ts +109 -0
- package/dist/types/data-structures/stack/stack.d.ts +82 -2
- package/dist/types/data-structures/trie/trie.d.ts +96 -0
- package/dist/types/interfaces/binary-tree.d.ts +2 -3
- package/dist/types/types/data-structures/binary-tree/bst.d.ts +1 -0
- package/dist/types/types/data-structures/binary-tree/tree-map.d.ts +5 -0
- package/dist/types/types/data-structures/binary-tree/tree-multi-set.d.ts +4 -0
- package/dist/types/types/data-structures/binary-tree/tree-set.d.ts +4 -0
- package/dist/umd/data-structure-typed.js +8623 -2564
- package/dist/umd/data-structure-typed.min.js +5 -5
- package/docs-site-docusaurus/docs/api/classes/AVLTree.md +696 -194
- package/docs-site-docusaurus/docs/api/classes/AVLTreeNode.md +11 -11
- package/docs-site-docusaurus/docs/api/classes/AbstractGraph.md +71 -71
- package/docs-site-docusaurus/docs/api/classes/BST.md +639 -189
- package/docs-site-docusaurus/docs/api/classes/BSTNode.md +13 -13
- package/docs-site-docusaurus/docs/api/classes/BinaryIndexedTree.md +15 -15
- package/docs-site-docusaurus/docs/api/classes/BinaryTree.md +148 -160
- package/docs-site-docusaurus/docs/api/classes/BinaryTreeNode.md +13 -13
- package/docs-site-docusaurus/docs/api/classes/Deque.md +105 -91
- package/docs-site-docusaurus/docs/api/classes/DirectedGraph.md +82 -82
- package/docs-site-docusaurus/docs/api/classes/DoublyLinkedList.md +104 -74
- package/docs-site-docusaurus/docs/api/classes/DoublyLinkedListNode.md +8 -8
- package/docs-site-docusaurus/docs/api/classes/FibonacciHeap.md +12 -12
- package/docs-site-docusaurus/docs/api/classes/FibonacciHeapNode.md +1 -1
- package/docs-site-docusaurus/docs/api/classes/HashMap.md +51 -51
- package/docs-site-docusaurus/docs/api/classes/Heap.md +96 -85
- package/docs-site-docusaurus/docs/api/classes/IterableElementBase.md +25 -25
- package/docs-site-docusaurus/docs/api/classes/IterableEntryBase.md +33 -33
- package/docs-site-docusaurus/docs/api/classes/LinearBase.md +50 -50
- package/docs-site-docusaurus/docs/api/classes/LinearLinkedBase.md +55 -55
- package/docs-site-docusaurus/docs/api/classes/LinkedHashMap.md +55 -55
- package/docs-site-docusaurus/docs/api/classes/LinkedListNode.md +6 -6
- package/docs-site-docusaurus/docs/api/classes/LinkedListQueue.md +78 -78
- package/docs-site-docusaurus/docs/api/classes/MapGraph.md +82 -82
- package/docs-site-docusaurus/docs/api/classes/Matrix.md +31 -31
- package/docs-site-docusaurus/docs/api/classes/MaxHeap.md +104 -89
- package/docs-site-docusaurus/docs/api/classes/MaxPriorityQueue.md +104 -89
- package/docs-site-docusaurus/docs/api/classes/MinHeap.md +104 -89
- package/docs-site-docusaurus/docs/api/classes/MinPriorityQueue.md +104 -89
- package/docs-site-docusaurus/docs/api/classes/Navigator.md +5 -5
- package/docs-site-docusaurus/docs/api/classes/PriorityQueue.md +103 -88
- package/docs-site-docusaurus/docs/api/classes/Queue.md +112 -60
- package/docs-site-docusaurus/docs/api/classes/RedBlackTree.md +708 -206
- package/docs-site-docusaurus/docs/api/classes/SegmentTree.md +10 -10
- package/docs-site-docusaurus/docs/api/classes/SinglyLinkedList.md +79 -79
- package/docs-site-docusaurus/docs/api/classes/SinglyLinkedListNode.md +6 -6
- package/docs-site-docusaurus/docs/api/classes/SkipList.md +44 -44
- package/docs-site-docusaurus/docs/api/classes/Stack.md +42 -42
- package/docs-site-docusaurus/docs/api/classes/TreeMap.md +236 -33
- package/docs-site-docusaurus/docs/api/classes/TreeMultiMap.md +162 -46
- package/docs-site-docusaurus/docs/api/classes/TreeSet.md +232 -32
- package/docs-site-docusaurus/docs/api/classes/Trie.md +47 -47
- package/docs-site-docusaurus/docs/api/classes/TrieNode.md +8 -8
- package/docs-site-docusaurus/docs/api/classes/UndirectedGraph.md +81 -81
- package/docs-site-docusaurus/docs/guide/architecture.md +75 -5
- package/docs-site-docusaurus/docs/guide/concepts.md +53 -3
- package/docs-site-docusaurus/docs/guide/faq.md +233 -0
- package/docs-site-docusaurus/docs/guide/guides.md +43 -58
- package/docs-site-docusaurus/docs/guide/installation.md +2 -0
- package/docs-site-docusaurus/docs/guide/integrations.md +75 -176
- package/docs-site-docusaurus/docs/guide/overview.md +132 -11
- package/docs-site-docusaurus/docs/guide/performance.md +2 -0
- package/docs-site-docusaurus/docs/guide/quick-start.md +31 -0
- package/docs-site-docusaurus/docs/guide/use-cases/_category_.json +6 -0
- package/docs-site-docusaurus/docs/guide/use-cases/array-sort-alternative.md +158 -0
- package/docs-site-docusaurus/docs/guide/use-cases/heap-vs-sorting.md +92 -0
- package/docs-site-docusaurus/docs/guide/use-cases/map-vs-treemap.md +151 -0
- package/docs-site-docusaurus/docs/guide/use-cases/priority-queue-typescript.md +113 -0
- package/docs-site-docusaurus/docs/guide/use-cases/treemap-javascript.md +151 -0
- package/docs-site-docusaurus/docusaurus.config.ts +1 -1
- package/docs-site-docusaurus/src/pages/index.tsx +55 -2
- package/docs-site-docusaurus/static/llms.txt +37 -0
- package/docs-site-docusaurus/typedoc.json +1 -0
- package/llms.txt +37 -0
- package/package.json +65 -56
- package/src/common/error.ts +19 -1
- package/src/common/index.ts +1 -1
- package/src/data-structures/base/iterable-element-base.ts +3 -2
- package/src/data-structures/binary-tree/avl-tree.ts +99 -5
- package/src/data-structures/binary-tree/binary-indexed-tree.ts +102 -4
- package/src/data-structures/binary-tree/binary-tree.ts +239 -78
- package/src/data-structures/binary-tree/bst.ts +542 -13
- package/src/data-structures/binary-tree/red-black-tree.ts +155 -15
- package/src/data-structures/binary-tree/segment-tree.ts +42 -0
- package/src/data-structures/binary-tree/tree-map.ts +1223 -261
- package/src/data-structures/binary-tree/tree-multi-map.ts +939 -30
- package/src/data-structures/binary-tree/tree-multi-set.ts +746 -10
- package/src/data-structures/binary-tree/tree-set.ts +1018 -99
- package/src/data-structures/graph/abstract-graph.ts +2 -2
- package/src/data-structures/graph/directed-graph.ts +71 -1
- package/src/data-structures/graph/undirected-graph.ts +64 -1
- package/src/data-structures/hash/hash-map.ts +102 -16
- package/src/data-structures/heap/heap.ts +153 -23
- package/src/data-structures/heap/max-heap.ts +2 -2
- package/src/data-structures/linked-list/doubly-linked-list.ts +139 -0
- package/src/data-structures/linked-list/singly-linked-list.ts +106 -1
- package/src/data-structures/linked-list/skip-linked-list.ts +131 -5
- package/src/data-structures/matrix/matrix.ts +65 -9
- package/src/data-structures/priority-queue/max-priority-queue.ts +2 -2
- package/src/data-structures/queue/deque.ts +130 -0
- package/src/data-structures/queue/queue.ts +109 -0
- package/src/data-structures/stack/stack.ts +75 -5
- package/src/data-structures/trie/trie.ts +86 -2
- package/src/interfaces/binary-tree.ts +1 -9
- package/src/types/data-structures/binary-tree/bst.ts +1 -0
- package/src/types/data-structures/binary-tree/tree-map.ts +6 -0
- package/src/types/data-structures/binary-tree/tree-multi-set.ts +5 -0
- package/src/types/data-structures/binary-tree/tree-set.ts +5 -0
- package/.vitepress/cache/deps_temp_51f5f1b0/chunk-7OIKW5WK.js +0 -12984
- package/.vitepress/cache/deps_temp_51f5f1b0/package.json +0 -3
- package/.vitepress/cache/deps_temp_51f5f1b0/vitepress___@vue_devtools-api.js +0 -4505
- package/.vitepress/cache/deps_temp_51f5f1b0/vitepress___@vueuse_core.js +0 -9731
- package/.vitepress/cache/deps_temp_51f5f1b0/vue.js +0 -347
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
---
|
|
2
2
|
sidebar_label: "ARCHITECTURE"
|
|
3
|
-
description: "
|
|
3
|
+
description: "Design philosophy, V8 JIT optimizations, self-balancing strategies, and internal architecture of data-structure-typed."
|
|
4
|
+
title: "Architecture — Design & Implementation Details"
|
|
5
|
+
keywords: ["data structures architecture", "red black tree implementation", "v8 optimization", "typescript library design"]
|
|
4
6
|
---
|
|
5
|
-
|
|
6
7
|
# ARCHITECTURE
|
|
7
8
|
|
|
8
9
|
Understand why this library is designed the way it is, and how it works internally.
|
|
9
10
|
|
|
10
|
-
**[Back to README](
|
|
11
|
+
**[Back to README](/docs/guide/quick-start) • [See Performance](/guide/performance.md) • [Real Examples](/guide/guides.md)**
|
|
11
12
|
|
|
12
13
|
---
|
|
13
14
|
|
|
@@ -483,7 +484,7 @@ class TreeStructure<K, V> {
|
|
|
483
484
|
return this; // Chain continues!
|
|
484
485
|
}
|
|
485
486
|
|
|
486
|
-
reduce(reducer: (acc:
|
|
487
|
+
reduce<A>(reducer: (acc: A, v: V, k: K) => A, init: A): A {
|
|
487
488
|
// ... reduce logic ...
|
|
488
489
|
return result; // Terminal operation
|
|
489
490
|
}
|
|
@@ -595,6 +596,74 @@ const objectTree = new RedBlackTree<CustomObject>([], {
|
|
|
595
596
|
|
|
596
597
|
---
|
|
597
598
|
|
|
599
|
+
## Order-Statistic Tree Architecture
|
|
600
|
+
|
|
601
|
+
### How `enableOrderStatistic` Works
|
|
602
|
+
|
|
603
|
+
When enabled, every node maintains a `_count` field — the number of nodes in its subtree (including itself).
|
|
604
|
+
|
|
605
|
+
```
|
|
606
|
+
8 (count=5)
|
|
607
|
+
/ \
|
|
608
|
+
3 10 (count=1)
|
|
609
|
+
(count=3)
|
|
610
|
+
/ \
|
|
611
|
+
1 6 (count=1)
|
|
612
|
+
(count=1)
|
|
613
|
+
```
|
|
614
|
+
|
|
615
|
+
### Count Maintenance
|
|
616
|
+
|
|
617
|
+
Counts are updated in every mutation path:
|
|
618
|
+
|
|
619
|
+
- **Insert** (`set`/`add`): `_updateCountAlongPath` increments counts from new node to root
|
|
620
|
+
- **Delete**: `_updateCountAlongPath` decrements counts from deleted position to root
|
|
621
|
+
- **Rotations** (AVL: `_balanceLL/LR/RR/RL`, RBT: `_leftRotate/_rightRotate`): `_updateCount` recalculates after structural changes
|
|
622
|
+
- **Balanced rebuild** (`setMany`, `perfectlyBalance`): counts rebuilt during tree construction
|
|
623
|
+
|
|
624
|
+
### Rank Operations
|
|
625
|
+
|
|
626
|
+
All O(log n) by walking down the tree using counts:
|
|
627
|
+
|
|
628
|
+
- **`getByRank(k)`**: Start at root. If left subtree count > k, go left. If equal, return current. Otherwise subtract and go right.
|
|
629
|
+
- **`getRank(key)`**: Walk to key, accumulating left subtree counts. Returns count of elements preceding key in tree order.
|
|
630
|
+
- **`rangeByRank(start, end)`**: Combine `getByRank` to find boundaries, then in-order collect.
|
|
631
|
+
|
|
632
|
+
### Opt-in Design
|
|
633
|
+
|
|
634
|
+
Order-statistic is **opt-in** (`enableOrderStatistic: true`) because:
|
|
635
|
+
- Extra count maintenance on every mutation adds O(log n) overhead
|
|
636
|
+
- Most users don't need rank queries
|
|
637
|
+
- `_snapshotOptions` preserves the flag through `clone()` and `map()`
|
|
638
|
+
|
|
639
|
+
---
|
|
640
|
+
|
|
641
|
+
## Error Handling: `raise()`
|
|
642
|
+
|
|
643
|
+
### Unified Error Strategy
|
|
644
|
+
|
|
645
|
+
All error throwing goes through `raise(ErrorType, message)` in `src/common/error.ts`:
|
|
646
|
+
|
|
647
|
+
```typescript
|
|
648
|
+
raise(TypeError, ERR.comparatorRequired('TreeMap'));
|
|
649
|
+
raise(RangeError, ERR.indexOutOfBounds(index, length));
|
|
650
|
+
```
|
|
651
|
+
|
|
652
|
+
### Why `raise()` Instead of Direct `throw`
|
|
653
|
+
|
|
654
|
+
1. **Single chokepoint** — all errors flow through one function for consistent behavior
|
|
655
|
+
2. **Error message templates** — `ERR` object provides standardized, reusable messages
|
|
656
|
+
3. **Future extensibility** — can add logging, telemetry, or error transformation without touching call sites
|
|
657
|
+
|
|
658
|
+
### Error Categories
|
|
659
|
+
|
|
660
|
+
| Error Type | When | Example |
|
|
661
|
+
|------------|------|---------|
|
|
662
|
+
| `TypeError` | Invalid input type | NaN key, missing comparator, non-function callback |
|
|
663
|
+
| `RangeError` | Out of bounds | Index beyond array length, invalid rank |
|
|
664
|
+
|
|
665
|
+
---
|
|
666
|
+
|
|
598
667
|
## Summary: Design Checklist
|
|
599
668
|
|
|
600
669
|
- ✅ Unified API across all structures
|
|
@@ -604,7 +673,8 @@ const objectTree = new RedBlackTree<CustomObject>([], {
|
|
|
604
673
|
- ✅ V8 JIT-friendly code
|
|
605
674
|
- ✅ Memory-efficient algorithms
|
|
606
675
|
- ✅ Full TypeScript support
|
|
607
|
-
- ✅
|
|
676
|
+
- ✅ Order-statistic tree with opt-in `enableOrderStatistic`
|
|
677
|
+
- ✅ Unified error handling via `raise()` + `ERR` templates
|
|
608
678
|
|
|
609
679
|
---
|
|
610
680
|
|
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
---
|
|
2
2
|
sidebar_label: "CONCEPTS"
|
|
3
|
-
description: "Core
|
|
3
|
+
description: "Core fundamentals and theory behind data-structure-typed. BST, balanced trees, heap, iterator protocol, and decision guide."
|
|
4
|
+
title: "Concepts — Core Fundamentals & Theory"
|
|
5
|
+
keywords: ["data structures concepts", "binary search tree", "balanced tree", "heap theory", "typescript data structures"]
|
|
4
6
|
---
|
|
5
|
-
|
|
6
7
|
# CONCEPTS
|
|
7
8
|
|
|
8
9
|
This guide explains the foundational concepts behind data structures through plain language and practical understanding.
|
|
9
10
|
|
|
10
|
-
**👈 [Back to README](
|
|
11
|
+
**👈 [Back to README](/docs/guide/quick-start) • [API Docs](https://data-structure-typed-docs.vercel.app/) • [Real-World Guides](/guide/guides.md)**
|
|
11
12
|
|
|
12
13
|
---
|
|
13
14
|
|
|
@@ -350,6 +351,49 @@ const matches = trie.getWords('appl');
|
|
|
350
351
|
// O(5 + 4) = 9 operations ✅
|
|
351
352
|
```
|
|
352
353
|
|
|
354
|
+
### Case 6: Finding the K-th Element or Rank
|
|
355
|
+
|
|
356
|
+
❌ Array requires sorting O(n log n):
|
|
357
|
+
|
|
358
|
+
```javascript
|
|
359
|
+
const scores = [85, 92, 78, 95, 88, 73, 99];
|
|
360
|
+
scores.sort((a, b) => b - a);
|
|
361
|
+
const thirdPlace = scores[2]; // Must re-sort after every insert
|
|
362
|
+
```
|
|
363
|
+
|
|
364
|
+
✅ Order-Statistic Tree gives O(log n) rank queries:
|
|
365
|
+
|
|
366
|
+
```javascript
|
|
367
|
+
const tree = new RedBlackTree(scores.map(s => [s, null]), {
|
|
368
|
+
comparator: (a, b) => b - a,
|
|
369
|
+
enableOrderStatistic: true
|
|
370
|
+
});
|
|
371
|
+
tree.getByRank(2); // 3rd place — O(log n)
|
|
372
|
+
tree.getRank(92); // How many scores are higher? — O(log n)
|
|
373
|
+
tree.rangeByRank(0, 2); // Top 3 scores — O(log n + k)
|
|
374
|
+
// Insert new score — O(log n), no re-sorting needed
|
|
375
|
+
tree.set(91, null);
|
|
376
|
+
```
|
|
377
|
+
|
|
378
|
+
### Case 7: Pass Raw Objects Without Pre-Processing
|
|
379
|
+
|
|
380
|
+
❌ Array.map just to reshape data:
|
|
381
|
+
|
|
382
|
+
```javascript
|
|
383
|
+
const users = [{ id: 3, name: 'Charlie' }, { id: 1, name: 'Alice' }];
|
|
384
|
+
const entries = users.map(u => [u.id, u]); // Extra step
|
|
385
|
+
const map = new Map(entries);
|
|
386
|
+
```
|
|
387
|
+
|
|
388
|
+
✅ Pass raw objects directly with `toEntryFn`:
|
|
389
|
+
|
|
390
|
+
```javascript
|
|
391
|
+
const map = new TreeMap(users, {
|
|
392
|
+
toEntryFn: u => [u.id, u]
|
|
393
|
+
});
|
|
394
|
+
// No .map() needed — sorted by id automatically
|
|
395
|
+
```
|
|
396
|
+
|
|
353
397
|
---
|
|
354
398
|
|
|
355
399
|
## 🎯 Decision Guide: Choose the Right Data Structure
|
|
@@ -386,6 +430,12 @@ Need range queries on an indexed sequence?
|
|
|
386
430
|
Only need prefix sums? → BinaryIndexedTree (simpler, less memory)
|
|
387
431
|
No → Continue
|
|
388
432
|
|
|
433
|
+
Need k-th element or rank queries?
|
|
434
|
+
↓
|
|
435
|
+
Yes → RedBlackTree / TreeMap / TreeSet with { enableOrderStatistic: true }
|
|
436
|
+
getByRank(k), getRank(key), rangeByRank(start, end) — all O(log n)
|
|
437
|
+
No → Continue
|
|
438
|
+
|
|
389
439
|
Need a sorted key-value map?
|
|
390
440
|
↓
|
|
391
441
|
Yes → TreeMap (guaranteed O(log n) via Red-Black Tree)
|
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
---
|
|
2
|
+
sidebar_label: "FAQ"
|
|
3
|
+
sidebar_position: 7
|
|
4
|
+
description: "Frequently asked questions about data-structure-typed."
|
|
5
|
+
title: "FAQ — Frequently Asked Questions"
|
|
6
|
+
keywords: ["data-structure-typed faq", "typescript data structures questions"]
|
|
7
|
+
---
|
|
8
|
+
# FAQ
|
|
9
|
+
|
|
10
|
+
---
|
|
11
|
+
title: FAQ — Frequently Asked Questions
|
|
12
|
+
sidebar_label: "FAQ"description: Common questions about data-structure-typed — TreeMap in JavaScript, priority queues, rank queries, bundle size, and more.
|
|
13
|
+
keywords: [typescript data structures, treemap javascript, priority queue typescript, sorted set javascript, rank query, faq]
|
|
14
|
+
sidebar_position: 7
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
# FAQ
|
|
18
|
+
|
|
19
|
+
## Does JavaScript have a TreeMap or TreeSet?
|
|
20
|
+
|
|
21
|
+
Not natively. JavaScript's `Map` and `Set` are hash-based and unordered. This library provides `TreeMap` and `TreeSet` backed by Red-Black Trees — offering sorted iteration, `floor`/`ceiling`/`higher`/`lower` lookups, and `getRank`/`getByRank`/`rangeByRank` queries.
|
|
22
|
+
|
|
23
|
+
```typescript
|
|
24
|
+
import { TreeMap } from 'data-structure-typed';
|
|
25
|
+
|
|
26
|
+
const map = new TreeMap<number, string>();
|
|
27
|
+
map.set(3, 'c');
|
|
28
|
+
map.set(1, 'a');
|
|
29
|
+
map.set(2, 'b');
|
|
30
|
+
|
|
31
|
+
// Sorted iteration (by key)
|
|
32
|
+
for (const [key, value] of map) {
|
|
33
|
+
console.log(key, value); // 1 'a', 2 'b', 3 'c'
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// NavigableMap operations
|
|
37
|
+
map.floor(2.5); // [2, 'b'] — largest key ≤ 2.5
|
|
38
|
+
map.ceiling(1.5); // [2, 'b'] — smallest key ≥ 1.5
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
## When should I use a Heap instead of sorting an array?
|
|
42
|
+
|
|
43
|
+
When you need to repeatedly access the smallest or largest element. Sorting an array is O(n log n) every time you add an element. A Heap gives you O(log n) insert and O(1) access to the top element.
|
|
44
|
+
|
|
45
|
+
**Use Heap when:**
|
|
46
|
+
- Building a priority queue or task scheduler
|
|
47
|
+
- Finding top-k elements from a stream
|
|
48
|
+
- Implementing Dijkstra's algorithm
|
|
49
|
+
- Any scenario where you repeatedly need the min/max
|
|
50
|
+
|
|
51
|
+
```typescript
|
|
52
|
+
import { MinHeap } from 'data-structure-typed';
|
|
53
|
+
|
|
54
|
+
const tasks = new MinHeap<number>([5, 1, 3, 7, 2]);
|
|
55
|
+
tasks.poll(); // 1 (O(log n), not O(n log n))
|
|
56
|
+
tasks.add(0);
|
|
57
|
+
tasks.peek(); // 0
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
## Does this library support rank and range queries?
|
|
61
|
+
|
|
62
|
+
Yes. Enable with `{ enableOrderStatistic: true }` on any tree-based structure:
|
|
63
|
+
|
|
64
|
+
```typescript
|
|
65
|
+
import { RedBlackTree } from 'data-structure-typed';
|
|
66
|
+
|
|
67
|
+
const tree = new RedBlackTree<number>([10, 20, 30, 40, 50], {
|
|
68
|
+
enableOrderStatistic: true
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
tree.getRank(30); // 2 — two elements precede 30 in tree order
|
|
72
|
+
tree.getByRank(0); // 10 — first element in tree order
|
|
73
|
+
tree.rangeByRank(1, 3); // [20, 30, 40] — positions 1 through 3
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
Works with `TreeMap`, `TreeSet`, `TreeMultiMap`, and `TreeMultiSet` too.
|
|
77
|
+
|
|
78
|
+
## Is it faster than native arrays for ordered operations?
|
|
79
|
+
|
|
80
|
+
For ordered insert + lookup: **yes, significantly**.
|
|
81
|
+
|
|
82
|
+
| Operation | Sorted Array | Red-Black Tree |
|
|
83
|
+
|-----------|-------------|----------------|
|
|
84
|
+
| Insert (maintain order) | O(n) | O(log n) |
|
|
85
|
+
| Find by key | O(log n) | O(log n) |
|
|
86
|
+
| Find min/max | O(1) | O(log n) |
|
|
87
|
+
| Delete by key | O(n) | O(log n) |
|
|
88
|
+
| Get kth element | O(1) | O(log n) |
|
|
89
|
+
|
|
90
|
+
For 10,000+ elements, the O(n) insert cost of arrays becomes a bottleneck. Trees maintain O(log n) regardless of size.
|
|
91
|
+
|
|
92
|
+
See [PERFORMANCE.md](https://github.com/zrwusa/data-structure-typed/blob/main/docs/PERFORMANCE.md) for benchmark results.
|
|
93
|
+
|
|
94
|
+
## Can I use this in React / Node.js / browser?
|
|
95
|
+
|
|
96
|
+
Yes. The library ships ESM, CJS, and UMD builds. It works in:
|
|
97
|
+
|
|
98
|
+
- **Node.js** (any version supporting ES2015+)
|
|
99
|
+
- **Browsers** (via bundler or UMD script tag)
|
|
100
|
+
- **React / Next.js / Vue / Angular** (import normally)
|
|
101
|
+
- **Deno / Bun** (ESM compatible)
|
|
102
|
+
|
|
103
|
+
Zero dependencies means no compatibility concerns.
|
|
104
|
+
|
|
105
|
+
## What data structures are included?
|
|
106
|
+
|
|
107
|
+
| Category | Structures |
|
|
108
|
+
|----------|-----------|
|
|
109
|
+
| Trees | RedBlackTree, AVLTree, BST, TreeMap, TreeSet, TreeMultiMap, TreeMultiSet |
|
|
110
|
+
| Heaps | Heap, MinHeap, MaxHeap, MinPriorityQueue, MaxPriorityQueue |
|
|
111
|
+
| Queues | Queue, Deque |
|
|
112
|
+
| Lists | SinglyLinkedList, DoublyLinkedList, SkipList |
|
|
113
|
+
| Hashing | HashMap |
|
|
114
|
+
| Graphs | DirectedGraph, UndirectedGraph |
|
|
115
|
+
| Strings | Trie |
|
|
116
|
+
| Arrays | SegmentTree, BinaryIndexedTree (Fenwick Tree), Matrix |
|
|
117
|
+
| Basic | Stack |
|
|
118
|
+
|
|
119
|
+
## Is this library production-ready?
|
|
120
|
+
|
|
121
|
+
Yes.
|
|
122
|
+
|
|
123
|
+
- **2600+ tests**, 99%+ code coverage
|
|
124
|
+
- **Zero dependencies**
|
|
125
|
+
- **Type-safe** — full TypeScript generics
|
|
126
|
+
- **Actively maintained** — regular releases
|
|
127
|
+
- Every release passes typecheck, lint, and full test suite via CI
|
|
128
|
+
|
|
129
|
+
## How does this compare to js-sdsl?
|
|
130
|
+
|
|
131
|
+
| Feature | data-structure-typed | js-sdsl |
|
|
132
|
+
|---------|---------------------|---------|
|
|
133
|
+
| Data structures | 20+ | ~6 |
|
|
134
|
+
| API style | Unified Array-like | Mixed |
|
|
135
|
+
| Order-statistic (getRank/getByRank) | ✅ | ❌ |
|
|
136
|
+
| Tree-shaking subpaths | ✅ | ❌ |
|
|
137
|
+
| Maintenance | Active (2026) | Inactive |
|
|
138
|
+
| Bundle (full) | ~143KB min | ~45KB min |
|
|
139
|
+
|
|
140
|
+
`data-structure-typed` is broader and more actively maintained. js-sdsl is smaller if you only need a few structures.
|
|
141
|
+
|
|
142
|
+
## What is the bundle size?
|
|
143
|
+
|
|
144
|
+
| Import | Size (ESM) |
|
|
145
|
+
|--------|-----------|
|
|
146
|
+
| Full bundle | 598KB |
|
|
147
|
+
| `data-structure-typed/binary-tree` | 315KB |
|
|
148
|
+
| `data-structure-typed/graph` | 127KB |
|
|
149
|
+
| `data-structure-typed/linked-list` | 93KB |
|
|
150
|
+
| `data-structure-typed/queue` | 91KB |
|
|
151
|
+
| `data-structure-typed/heap` | 36KB |
|
|
152
|
+
| `data-structure-typed/priority-queue` | 30KB |
|
|
153
|
+
| `data-structure-typed/hash` | 29KB |
|
|
154
|
+
| `data-structure-typed/matrix` | 28KB |
|
|
155
|
+
| `data-structure-typed/trie` | 27KB |
|
|
156
|
+
| `data-structure-typed/stack` | 18KB |
|
|
157
|
+
|
|
158
|
+
UMD bundle: ~143KB minified. `sideEffects: false` enables full tree-shaking with modern bundlers.
|
|
159
|
+
|
|
160
|
+
## Can I pass raw data without converting it first?
|
|
161
|
+
|
|
162
|
+
Yes. Three patterns depending on what you want to store:
|
|
163
|
+
|
|
164
|
+
```typescript
|
|
165
|
+
interface User {
|
|
166
|
+
id: number;
|
|
167
|
+
name: string;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
const users: User[] = [
|
|
171
|
+
{ id: 3, name: 'Charlie' },
|
|
172
|
+
{ id: 1, name: 'Alice' },
|
|
173
|
+
{ id: 2, name: 'Bob' }
|
|
174
|
+
];
|
|
175
|
+
|
|
176
|
+
// 1. Extract a field — only that field is stored
|
|
177
|
+
const ids = new TreeSet<number, User>(
|
|
178
|
+
users,
|
|
179
|
+
{ toElementFn: u => u.id }
|
|
180
|
+
);
|
|
181
|
+
// [1, 2, 3]
|
|
182
|
+
|
|
183
|
+
// 2. Store full objects — sort by a field (raw data preserved!)
|
|
184
|
+
const fullSet = new TreeSet<User>(
|
|
185
|
+
users,
|
|
186
|
+
{ comparator: (a, b) => a.id - b.id }
|
|
187
|
+
);
|
|
188
|
+
// [{ id: 1, name: 'Alice' }, { id: 2, ... }, { id: 3, ... }]
|
|
189
|
+
|
|
190
|
+
// 3. Split into key-value — key for lookup, full object as value
|
|
191
|
+
const map = new TreeMap<number, User, User>(
|
|
192
|
+
users,
|
|
193
|
+
{ toEntryFn: u => [u.id, u] }
|
|
194
|
+
);
|
|
195
|
+
// map.get(1) → { id: 1, name: 'Alice' }
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
| I want to... | Use |
|
|
199
|
+
|---|---|
|
|
200
|
+
| Store only IDs/scores/prices | `toElementFn` |
|
|
201
|
+
| Store full objects, sorted by a field | `comparator` |
|
|
202
|
+
| Look up full objects by a key | `toEntryFn` |
|
|
203
|
+
|
|
204
|
+
## How do I build a leaderboard with this library?
|
|
205
|
+
|
|
206
|
+
```typescript
|
|
207
|
+
import { TreeMap } from 'data-structure-typed';
|
|
208
|
+
|
|
209
|
+
const leaderboard = new TreeMap<number, string>(
|
|
210
|
+
[[100, 'Alice'], [250, 'Bob'], [180, 'Charlie']],
|
|
211
|
+
{ comparator: (a, b) => b - a, enableOrderStatistic: true }
|
|
212
|
+
);
|
|
213
|
+
|
|
214
|
+
// Top 3 players (descending score order)
|
|
215
|
+
leaderboard.rangeByRank(0, 2);
|
|
216
|
+
// → [[250, 'Bob'], [180, 'Charlie'], [100, 'Alice']]
|
|
217
|
+
|
|
218
|
+
// What rank is score 180?
|
|
219
|
+
leaderboard.getRank(180); // 1 (0-indexed, second position)
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
## How do I build autocomplete with a Trie?
|
|
223
|
+
|
|
224
|
+
```typescript
|
|
225
|
+
import { Trie } from 'data-structure-typed';
|
|
226
|
+
|
|
227
|
+
const trie = new Trie(['apple', 'app', 'application', 'banana', 'band']);
|
|
228
|
+
|
|
229
|
+
trie.getWords('app'); // ['app', 'apple', 'application']
|
|
230
|
+
trie.getWords('ban'); // ['banana', 'band']
|
|
231
|
+
trie.hasPrefix('app'); // true
|
|
232
|
+
trie.has('apple'); // true
|
|
233
|
+
```
|
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
---
|
|
2
2
|
sidebar_label: "GUIDES"
|
|
3
|
-
description: "Real-world examples
|
|
3
|
+
description: "Real-world examples and production patterns for data-structure-typed."
|
|
4
|
+
title: "Guides — Real-World Examples & Production Patterns"
|
|
5
|
+
keywords: ["data-structure-typed examples", "typescript data structures patterns", "production code examples"]
|
|
4
6
|
---
|
|
5
|
-
|
|
6
7
|
# GUIDES
|
|
7
8
|
|
|
8
9
|
Production-ready code examples for common use cases. Learn by doing.
|
|
9
10
|
|
|
10
|
-
**[Back to README](
|
|
11
|
+
**[Back to README](/docs/guide/quick-start) • [API Docs](https://data-structure-typed-docs.vercel.app/) • [See INTEGRATIONS](/guide/integrations.md)**
|
|
11
12
|
|
|
12
13
|
---
|
|
13
14
|
|
|
@@ -146,7 +147,7 @@ If you insert keys in sorted or nearly-sorted order (timestamps, auto-increment
|
|
|
146
147
|
import { RedBlackTree } from 'data-structure-typed';
|
|
147
148
|
import type { RedBlackTreeNode } from 'data-structure-typed';
|
|
148
149
|
|
|
149
|
-
const tree = new RedBlackTree<number, number>(
|
|
150
|
+
const tree = new RedBlackTree<number, number>();
|
|
150
151
|
|
|
151
152
|
let hint: RedBlackTreeNode<number, number> | undefined;
|
|
152
153
|
for (let i = 0; i < 1_000_000; i++) {
|
|
@@ -170,7 +171,7 @@ Notes:
|
|
|
170
171
|
import { DoublyLinkedList } from 'data-structure-typed';
|
|
171
172
|
|
|
172
173
|
class LRUCache<K, V> {
|
|
173
|
-
private cache = new Map<K, { value: V; node:
|
|
174
|
+
private cache = new Map<K, { value: V; node: DoublyLinkedList<K> }>();
|
|
174
175
|
private order = new DoublyLinkedList<K>();
|
|
175
176
|
private readonly capacity: number;
|
|
176
177
|
|
|
@@ -222,7 +223,7 @@ cache.set('d', 'value4'); // Evicts 'b' (least recent)
|
|
|
222
223
|
|
|
223
224
|
```typescript
|
|
224
225
|
import { RedBlackTree } from 'data-structure-typed';
|
|
225
|
-
|
|
226
|
+
|
|
226
227
|
interface Player {
|
|
227
228
|
id: string;
|
|
228
229
|
name: string;
|
|
@@ -230,76 +231,58 @@ interface Player {
|
|
|
230
231
|
}
|
|
231
232
|
|
|
232
233
|
class Leaderboard {
|
|
234
|
+
// enableOrderStatistic gives O(log n) getByRank/getRank/rangeByRank
|
|
233
235
|
private scores = new RedBlackTree<number, Player>(
|
|
234
|
-
|
|
236
|
+
[],
|
|
237
|
+
{ comparator: (a, b) => b - a, enableOrderStatistic: true }
|
|
235
238
|
);
|
|
236
239
|
private players = new Map<string, number>(); // playerId → currentScore
|
|
237
240
|
|
|
238
241
|
updateScore(player: Player): void {
|
|
239
|
-
// Remove old score if exists
|
|
240
242
|
if (this.players.has(player.id)) {
|
|
241
|
-
|
|
242
|
-
this.scores.delete(oldScore);
|
|
243
|
+
this.scores.delete(this.players.get(player.id)!);
|
|
243
244
|
}
|
|
244
|
-
|
|
245
|
-
// Add new score
|
|
246
245
|
this.scores.set(player.score, player);
|
|
247
246
|
this.players.set(player.id, player.score);
|
|
248
247
|
}
|
|
249
248
|
|
|
250
|
-
// O(k
|
|
249
|
+
// O(k) — select by rank, no array copy
|
|
251
250
|
getTopN(n: number): Player[] {
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
const player = this.scores.get(key);
|
|
256
|
-
if (player) result.push(player);
|
|
257
|
-
key = this.scores.higher(key); // next in tree order
|
|
258
|
-
}
|
|
259
|
-
return result;
|
|
251
|
+
return this.scores.rangeByRank(0, n - 1)
|
|
252
|
+
.map(key => key !== undefined ? this.scores.get(key) : undefined)
|
|
253
|
+
.filter((p): p is Player => p !== undefined);
|
|
260
254
|
}
|
|
261
255
|
|
|
262
|
-
// O(log n
|
|
256
|
+
// O(log n) — direct rank lookup
|
|
263
257
|
getRank(playerId: string): number {
|
|
264
258
|
if (!this.players.has(playerId)) return -1;
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
return rank;
|
|
259
|
+
return this.scores.getRank(this.players.get(playerId)!) + 1; // 1-based
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
// O(log n) — get k-th player by rank
|
|
263
|
+
getPlayerAt(rank: number): Player | undefined {
|
|
264
|
+
const key = this.scores.getByRank(rank - 1); // 0-indexed internally
|
|
265
|
+
return key !== undefined ? this.scores.get(key) : undefined;
|
|
273
266
|
}
|
|
274
267
|
|
|
275
|
-
// O(log n + k) —
|
|
268
|
+
// O(log n + k) — players around a given player
|
|
276
269
|
getAroundMe(playerId: string, range: number): Player[] {
|
|
277
270
|
if (!this.players.has(playerId)) return [];
|
|
278
|
-
const
|
|
279
|
-
const
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
const p = this.scores.get(key);
|
|
286
|
-
if (p) above.unshift(p);
|
|
287
|
-
key = this.scores.lower(key);
|
|
288
|
-
}
|
|
289
|
-
|
|
290
|
-
// Me + `range` players below me
|
|
291
|
-
result.push(...above);
|
|
292
|
-
const me = this.scores.get(myScore);
|
|
293
|
-
if (me) result.push(me);
|
|
294
|
-
|
|
295
|
-
key = this.scores.higher(myScore);
|
|
296
|
-
for (let i = 0; i < range && key !== undefined; i++) {
|
|
297
|
-
const p = this.scores.get(key);
|
|
298
|
-
if (p) result.push(p);
|
|
299
|
-
key = this.scores.higher(key);
|
|
300
|
-
}
|
|
271
|
+
const myRank = this.scores.getRank(this.players.get(playerId)!);
|
|
272
|
+
const start = Math.max(0, myRank - range);
|
|
273
|
+
const end = Math.min(this.scores.size - 1, myRank + range);
|
|
274
|
+
return this.scores.rangeByRank(start, end)
|
|
275
|
+
.map(key => key !== undefined ? this.scores.get(key) : undefined)
|
|
276
|
+
.filter((p): p is Player => p !== undefined);
|
|
277
|
+
}
|
|
301
278
|
|
|
302
|
-
|
|
279
|
+
// Pagination: show page N of the leaderboard
|
|
280
|
+
getPage(page: number, pageSize: number): Player[] {
|
|
281
|
+
const start = (page - 1) * pageSize;
|
|
282
|
+
const end = start + pageSize - 1;
|
|
283
|
+
return this.scores.rangeByRank(start, end)
|
|
284
|
+
.map(key => key !== undefined ? this.scores.get(key) : undefined)
|
|
285
|
+
.filter((p): p is Player => p !== undefined);
|
|
303
286
|
}
|
|
304
287
|
}
|
|
305
288
|
|
|
@@ -309,9 +292,11 @@ lb.updateScore({ id: '1', name: 'Alice', score: 1000 });
|
|
|
309
292
|
lb.updateScore({ id: '2', name: 'Bob', score: 900 });
|
|
310
293
|
lb.updateScore({ id: '3', name: 'Charlie', score: 950 });
|
|
311
294
|
|
|
312
|
-
console.log(lb.getTopN(2));
|
|
313
|
-
console.log(lb.getRank('2'));
|
|
314
|
-
console.log(lb.
|
|
295
|
+
console.log(lb.getTopN(2)); // Alice, Charlie
|
|
296
|
+
console.log(lb.getRank('2')); // 3 (Bob is 3rd)
|
|
297
|
+
console.log(lb.getPlayerAt(1)); // Alice (1st place)
|
|
298
|
+
console.log(lb.getAroundMe('3', 1)); // [Alice, Charlie, Bob]
|
|
299
|
+
console.log(lb.getPage(1, 2)); // [Alice, Charlie] (page 1, 2 per page)
|
|
315
300
|
```
|
|
316
301
|
|
|
317
302
|
### Example 3: Message Queue with Priorities
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
description: "Install data-structure-typed via npm, yarn, or pnpm. Supports tree-shaking with subpath imports for minimal bundle size."
|
|
3
|
+
title: "Installation — npm, yarn, pnpm"
|
|
4
|
+
sidebar_label: "INSTALLATION"keywords: [data-structure-typed install, npm data structures, typescript library install, tree shaking, subpath imports]
|
|
3
5
|
---
|
|
4
6
|
|
|
5
7
|
# Installation
|