data-structure-typed 2.2.1 â 2.2.2
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 +3 -1
- package/README.md +1511 -885
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -9,15 +9,36 @@
|
|
|
9
9
|

|
|
10
10
|

|
|
11
11
|
|
|
12
|
-
|
|
12
|
+
### đ Uniform API: Coding feels like home.
|
|
13
|
+
> Don't learn new APIs. Just use `push`, `pop`, `map`, `filter`, and `reduce` everywhere.
|
|
13
14
|
|
|
14
|
-
|
|
15
|
+
### ⥠High Performance: Speed without compromise.
|
|
16
|
+
> Benchmarks prove it. We outperform native implementations in critical scenarios.
|
|
15
17
|
|
|
18
|
+
### đĄī¸ Type Safe: TypeScript first, always.
|
|
19
|
+
> No more `any`. Enjoy full generics and strict type checking out of the box.
|
|
16
20
|
|
|
17
|
-
|
|
21
|
+
### ⨠Zero Friction: It just plays nice.
|
|
22
|
+
> Works with everything. Spread it `[...]`, loop it `for..of`, or convert it instantly.
|
|
18
23
|
|
|
19
24
|
## Installation and Usage
|
|
20
25
|
|
|
26
|
+
### pnpm
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
pnpm add data-structure-typed
|
|
30
|
+
```
|
|
31
|
+
### Playground
|
|
32
|
+
|
|
33
|
+
[Node.js TypeScript](https://stackblitz.com/edit/stackblitz-starters-e1vdy3zw?file=src%2Findex.ts)
|
|
34
|
+
|
|
35
|
+
[Node.js JavaScript](https://stackblitz.com/edit/stackblitz-starters-dgvchziu?file=src%2Findex.js)
|
|
36
|
+
|
|
37
|
+
[React TypeScript](https://stackblitz.com/edit/vitejs-vite-6xvhtdua?file=src%2FApp.tsx)
|
|
38
|
+
|
|
39
|
+
[NestJS TypeScript](https://stackblitz.com/edit/nestjs-typescript-starter-3cyp7pel?file=src%2Franking%2Franking.service.ts&terminal=start:dev)
|
|
40
|
+
|
|
41
|
+
|
|
21
42
|
### npm
|
|
22
43
|
|
|
23
44
|
```bash
|
|
@@ -30,7 +51,53 @@ npm i data-structure-typed --save
|
|
|
30
51
|
yarn add data-structure-typed
|
|
31
52
|
```
|
|
32
53
|
|
|
33
|
-
|
|
54
|
+
### Individual Data Structure Installation
|
|
55
|
+
|
|
56
|
+
If you only want to use a specific data structure independently:
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
npm i heap-typed --save
|
|
60
|
+
npm i bst-typed --save
|
|
61
|
+
npm i red-black-tree-typed --save
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
---
|
|
66
|
+
|
|
67
|
+
## đ Quick Navigation
|
|
68
|
+
|
|
69
|
+
Choose your learning path based on your needs:
|
|
70
|
+
|
|
71
|
+
### đ¤ I'm New Here
|
|
72
|
+
|
|
73
|
+
- âąī¸ **3 Minutes to Productivity**: [Quick Start](#quick-start-3-minutes-to-productivity)
|
|
74
|
+
- đ **Full Understanding**: [Why data-structure-typed?](#why-data-structure-typed)
|
|
75
|
+
- đģ **Show Me Code**: [Code Snippets](#code-snippets-patterns--examples)
|
|
76
|
+
|
|
77
|
+
### đ¤ Not Sure Which Data Structure to Use?
|
|
78
|
+
|
|
79
|
+
- đ¯ **Decision Guide**: [Choose Your Data Structure](#-decision-guide-choose-the-right-data-structure)
|
|
80
|
+
- đ **Data Structures Overview**: [Complete List](#-data-structures-available)
|
|
81
|
+
|
|
82
|
+
### đ Migrating from Native JavaScript?
|
|
83
|
+
|
|
84
|
+
- đ **Migration Guide**: [From Array to Specialized Structures](#-migration-guide-from-native-js)
|
|
85
|
+
- đ **Integration Examples**: [React, Express, Nest.js](#-integration-examples)
|
|
86
|
+
|
|
87
|
+
### đ Performance-Focused?
|
|
88
|
+
|
|
89
|
+
- ⥠**Performance Data**: [Benchmark Results](#-performance-comparison)
|
|
90
|
+
- đ **Real Cases**: [5 Production Code Examples](#-real-world-examples-production-code)
|
|
91
|
+
|
|
92
|
+
### đĸ Enterprise Integration?
|
|
93
|
+
|
|
94
|
+
- đ **Framework Integration**: [React, Vue, Express, Nest.js, Next.js](#-integration-examples)
|
|
95
|
+
- đ ī¸ **Multi-Environment**: [CDN/CommonJS/ESModule/TypeScript](#supported-module-system)
|
|
96
|
+
|
|
97
|
+
---
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
### Quick Verification
|
|
34
101
|
|
|
35
102
|
```js
|
|
36
103
|
import {
|
|
@@ -38,227 +105,1166 @@ import {
|
|
|
38
105
|
AVLTree, SinglyLinkedList, DirectedGraph, RedBlackTree, TreeMultiMap,
|
|
39
106
|
DirectedVertex, Stack, AVLTreeNode
|
|
40
107
|
} from 'data-structure-typed';
|
|
108
|
+
|
|
109
|
+
// Quick test
|
|
110
|
+
const tree = new RedBlackTree([5, 2, 8, 1, 9]);
|
|
111
|
+
console.log([...tree.keys()]); // [1, 2, 5, 8, 9]
|
|
41
112
|
```
|
|
42
113
|
|
|
43
|
-
|
|
114
|
+
---
|
|
44
115
|
|
|
45
|
-
|
|
46
|
-
|
|
116
|
+
## Quick Start: 3 Minutes to Productivity
|
|
117
|
+
|
|
118
|
+
### Scenario 1: High-Performance Queue
|
|
119
|
+
|
|
120
|
+
**Problem**: You need to frequently remove elements from the front of a list.
|
|
121
|
+
|
|
122
|
+
â This is slow with Array:
|
|
123
|
+
|
|
124
|
+
```javascript
|
|
125
|
+
const queue = [1, 2, 3, 4, 5];
|
|
126
|
+
queue.shift(); // O(n) - Reindexes all remaining elements!
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
â
This is fast with Deque:
|
|
130
|
+
|
|
131
|
+
```javascript
|
|
132
|
+
import { Deque } from 'data-structure-typed';
|
|
133
|
+
|
|
134
|
+
const deque = new Deque([1, 2, 3, 4, 5]);
|
|
135
|
+
deque.shift(); // O(1) - Just moves a pointer
|
|
136
|
+
deque.print(); // [2, 3, 4, 5]
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
---
|
|
140
|
+
|
|
141
|
+
### Scenario 2: Sorted Data with Fast Lookups
|
|
142
|
+
|
|
143
|
+
**Problem**: You need to maintain sorted data and query it efficiently.
|
|
144
|
+
|
|
145
|
+
â Array requires manual sorting:
|
|
146
|
+
|
|
147
|
+
```javascript
|
|
148
|
+
const arr = [5, 2, 8, 1, 9];
|
|
149
|
+
arr.includes(3); // O(n) - Must check every element
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
â
RedBlackTree maintains sorted order automatically:
|
|
153
|
+
|
|
154
|
+
```javascript
|
|
155
|
+
import { RedBlackTree } from 'data-structure-typed';
|
|
156
|
+
|
|
157
|
+
const tree = new RedBlackTree([5, 2, 8, 1, 9]);
|
|
158
|
+
tree.has(3); // O(log n) - Logarithmic search
|
|
159
|
+
|
|
160
|
+
// Iterating tree is already sorted
|
|
161
|
+
for (const [key] of tree) {
|
|
162
|
+
console.log(key); // 1, 2, 5, 8, 9 (automatically sorted!)
|
|
163
|
+
}
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
---
|
|
167
|
+
|
|
168
|
+
### Scenario 3: Priority Queue
|
|
169
|
+
|
|
170
|
+
**Problem**: Process items by priority, not insertion order.
|
|
171
|
+
|
|
172
|
+
â Array requires re-sorting:
|
|
173
|
+
|
|
174
|
+
```javascript
|
|
175
|
+
const tasks = [];
|
|
176
|
+
|
|
177
|
+
function addTask(task) {
|
|
178
|
+
tasks.push(task);
|
|
179
|
+
tasks.sort((a, b) => b.priority - a.priority); // O(n log n) every time!
|
|
180
|
+
}
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
â
PriorityQueue maintains priority automatically:
|
|
184
|
+
|
|
185
|
+
```javascript
|
|
186
|
+
import { MaxPriorityQueue } from 'data-structure-typed';
|
|
187
|
+
|
|
188
|
+
const pq = new MaxPriorityQueue([], {
|
|
189
|
+
comparator: (a, b) => b.priority - a.priority,
|
|
190
|
+
});
|
|
191
|
+
|
|
192
|
+
function addTask(task) {
|
|
193
|
+
pq.add(task); // O(log n)
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
const nextTask = pq.poll(); // Always get highest priority
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
---
|
|
200
|
+
|
|
201
|
+
### Scenario 4: Prefix Matching (Autocomplete)
|
|
202
|
+
|
|
203
|
+
**Problem**: Fast prefix searching in large dictionaries.
|
|
204
|
+
|
|
205
|
+
```javascript
|
|
206
|
+
import { Trie } from 'data-structure-typed';
|
|
207
|
+
|
|
208
|
+
const dictionary = new Trie(['apple', 'app', 'apply', 'application']);
|
|
209
|
+
|
|
210
|
+
const suggestions = dictionary.getWords('appl');
|
|
211
|
+
// Returns: ['apple', 'apply', 'application']
|
|
212
|
+
// Time: O(m + k) where m is prefix length, k is results
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
---
|
|
216
|
+
|
|
217
|
+
### Scenario 5: Graph Algorithms
|
|
218
|
+
|
|
219
|
+
**Problem**: Pathfinding or cycle detection.
|
|
220
|
+
|
|
221
|
+
```javascript
|
|
222
|
+
import { DirectedGraph } from 'data-structure-typed';
|
|
223
|
+
|
|
224
|
+
const graph = new DirectedGraph();
|
|
225
|
+
graph.addVertex('A');
|
|
226
|
+
graph.addVertex('B');
|
|
227
|
+
graph.addEdge('A', 'B', 1);
|
|
228
|
+
|
|
229
|
+
const { minDist, minPath } = graph.dijkstra('A', 'B', true, true);
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
---
|
|
233
|
+
|
|
234
|
+
## Why data-structure-typed?
|
|
235
|
+
|
|
236
|
+
> All data structures in JavaScript should work like native Array.
|
|
237
|
+
> No more API chaos. No more conversions. No more frustration.
|
|
238
|
+
|
|
239
|
+
### Three Pain Points Every Developer Faces
|
|
240
|
+
|
|
241
|
+
#### 1ī¸âŖ Performance Wall: When Operations Become Bottlenecks
|
|
242
|
+
|
|
243
|
+
â The Problem: Array.shift() is O(n):
|
|
244
|
+
|
|
245
|
+
```javascript
|
|
246
|
+
const queue = [1, 2, 3, ..., 100000];
|
|
247
|
+
for (let i = 0; i < 100000; i++) {
|
|
248
|
+
queue.shift(); // Reindexes all remaining elements!
|
|
249
|
+
}
|
|
250
|
+
// Time: 2829ms for 100K items â
|
|
251
|
+
// Impact: Timeout, failed test
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
â
The Solution: Use Deque:
|
|
255
|
+
|
|
256
|
+
```javascript
|
|
257
|
+
import { Deque } from 'data-structure-typed';
|
|
258
|
+
|
|
259
|
+
const deque = new Deque([1, 2, 3, ..., 100000]);
|
|
260
|
+
for (let i = 0; i < 100000; i++) {
|
|
261
|
+
deque.shift(); // O(1) - Just moves a pointer
|
|
262
|
+
}
|
|
263
|
+
// Time: 5.83ms for 100K items â
|
|
264
|
+
// Speedup: 484x faster! đ
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
**Real-world impact:**
|
|
268
|
+
|
|
269
|
+
- Competitive programming: TLE â â AC â
|
|
270
|
+
- Real-time systems: P99 latency 500ms â â 5ms â
|
|
271
|
+
- Message queues: Throughput 100/sec â â 10,000/sec â
|
|
272
|
+
|
|
273
|
+
#### 2ī¸âŖ API Chaos: Learning a New API for Every Data Structure
|
|
274
|
+
|
|
275
|
+
â Different libraries use different APIs:
|
|
276
|
+
|
|
277
|
+
```javascript
|
|
278
|
+
// Library 1: Uses offer/poll (Java-style)
|
|
279
|
+
queue.offer(item);
|
|
280
|
+
queue.poll();
|
|
281
|
+
|
|
282
|
+
// Library 2: Uses push/shift
|
|
283
|
+
queue.push(item);
|
|
284
|
+
queue.shift();
|
|
285
|
+
|
|
286
|
+
// Library 3: Uses enqueue/dequeue
|
|
287
|
+
queue.enqueue(item);
|
|
288
|
+
queue.dequeue();
|
|
289
|
+
```
|
|
290
|
+
|
|
291
|
+
â
Our library uses consistent APIs everywhere:
|
|
292
|
+
|
|
293
|
+
In [java.utils](), you need to memorize different methods for Queue, Deque, LinkedList:
|
|
294
|
+
|
|
295
|
+
| Java ArrayList | Java Queue | Java ArrayDeque | Java LinkedList |
|
|
296
|
+
|---|---|---|---|
|
|
297
|
+
| add | offer | push | push |
|
|
298
|
+
| remove | poll | removeLast | removeLast |
|
|
299
|
+
| remove | poll | removeFirst | removeFirst |
|
|
300
|
+
| add(0, element) | offerFirst | unshift | unshift |
|
|
301
|
+
|
|
302
|
+
**In data-structure-typed, you only need to remember four methods**: `push`, `pop`, `shift`, and `unshift` for all linear structures (Queue, Deque, DoublyLinkedList, SinglyLinkedList, Stack).
|
|
303
|
+
|
|
304
|
+
```javascript
|
|
305
|
+
// ALL linear structures use THE SAME 4 methods
|
|
306
|
+
const deque = new Deque([1, 2, 3]);
|
|
307
|
+
const queue = new Queue([1, 2, 3]);
|
|
308
|
+
const stack = new Stack([1, 2, 3]);
|
|
309
|
+
const list = new DoublyLinkedList([1, 2, 3]);
|
|
310
|
+
|
|
311
|
+
// They ALL support:
|
|
312
|
+
structure.push(item); // Add to end
|
|
313
|
+
structure.pop(); // Remove from end
|
|
314
|
+
structure.shift(); // Remove from start
|
|
315
|
+
structure.unshift(item); // Add to start
|
|
316
|
+
|
|
317
|
+
// And ALL support Array's advanced methods
|
|
318
|
+
structure.map((_value, key) => key * 2);
|
|
319
|
+
structure.filter((_value, key) => key > 5);
|
|
320
|
+
structure.reduce((acc, _value, key) => acc + key, 0);
|
|
321
|
+
```
|
|
322
|
+
|
|
323
|
+
#### 3ī¸âŖ Conversion Hell: Bouncing Data Between Structures
|
|
324
|
+
|
|
325
|
+
â The Painful Way:
|
|
326
|
+
|
|
327
|
+
```javascript
|
|
328
|
+
const scores = [95, 23, 67, 89, 12, 45];
|
|
329
|
+
const tree = new SomeTreeLibrary(scores);
|
|
330
|
+
|
|
331
|
+
const filtered = tree.toArray().filter(s => s > 50); // Convert to array
|
|
332
|
+
const mapped = filtered.map(s => s * 2); // Another conversion
|
|
333
|
+
// Multiple conversions, lost benefits, easy to make mistakes
|
|
334
|
+
```
|
|
335
|
+
|
|
336
|
+
â
The Clean Way:
|
|
337
|
+
|
|
338
|
+
```javascript
|
|
339
|
+
const tree = new RedBlackTree(scores);
|
|
340
|
+
|
|
341
|
+
// All methods work DIRECTLY on the tree
|
|
342
|
+
const result = tree
|
|
343
|
+
.filter((_value, key) => key > 50) // Direct
|
|
344
|
+
.map((_value, key) => [key, key * 1]) // Direct
|
|
345
|
+
.reduce((acc, value) => acc + (value ?? 0), 0); // Direct
|
|
346
|
+
|
|
347
|
+
// â
Zero conversions, tree structure maintained
|
|
348
|
+
```
|
|
349
|
+
|
|
350
|
+
---
|
|
351
|
+
|
|
352
|
+
## đ Seamless Interoperability: Iterator Protocol Everywhere
|
|
353
|
+
|
|
354
|
+
### The Hidden Superpower
|
|
355
|
+
|
|
356
|
+
Every single data structure implements the **Iterator protocol**:
|
|
357
|
+
|
|
358
|
+
- â
Spread operator: `[...tree]`
|
|
359
|
+
- â
for...of loops: `for (const item of tree)`
|
|
360
|
+
- â
Destructuring: `const [a, b, c] = tree`
|
|
361
|
+
- â
Array.from(): `Array.from(tree)`
|
|
362
|
+
- â
Set/Map constructors: `new Set(tree)`
|
|
363
|
+
|
|
364
|
+
### Iterator Support Comparison
|
|
365
|
+
|
|
366
|
+
| Feature | Array | Map | Set | Other Lib | data-structure-typed |
|
|
367
|
+
|---------|-------|-----|-----|-----------|----------------------|
|
|
368
|
+
| Spread operator | â
| â/â ī¸ | â
| â/â ī¸ | â
|
|
|
369
|
+
| for...of loop | â
| â
| â
| â/â ī¸ | â
|
|
|
370
|
+
| Destructuring | â
| â | â | â | â
|
|
|
371
|
+
| Array.from() | â
| â/â ī¸ | â | â/â ī¸ | â
|
|
|
372
|
+
| Set constructor | â
| â | â
| â | â
|
|
|
373
|
+
| **Full Integration** | â
| â ī¸ | â ī¸ | â ī¸ | **â
** |
|
|
374
|
+
|
|
375
|
+
### Live Examples: Zero Friction Conversions
|
|
376
|
+
|
|
377
|
+
#### Example 1: Array to Tree to Array
|
|
378
|
+
|
|
379
|
+
```javascript
|
|
380
|
+
const array = [64, 34, 25, 12, 22, 11, 90];
|
|
381
|
+
const rbTree = new RedBlackTree(array);
|
|
382
|
+
const sorted = [...rbTree.keys()];
|
|
383
|
+
console.log(sorted); // [11, 12, 22, 25, 34, 64, 90] â
|
|
384
|
+
```
|
|
385
|
+
|
|
386
|
+
#### Example 2: Extract Keys and Values
|
|
387
|
+
|
|
388
|
+
```javascript
|
|
389
|
+
const rbTree = new RedBlackTree([
|
|
390
|
+
[1, 'Alice'],
|
|
391
|
+
[2, 'Bob'],
|
|
392
|
+
[3, 'Charlie']
|
|
393
|
+
]);
|
|
394
|
+
|
|
395
|
+
const allKeys = [...rbTree.keys()]; // [1, 2, 3]
|
|
396
|
+
const allValues = [...rbTree.values()]; // ['Alice', 'Bob', 'Charlie']
|
|
397
|
+
```
|
|
398
|
+
|
|
399
|
+
#### Example 3: for...of on Any Structure
|
|
400
|
+
|
|
401
|
+
```javascript
|
|
402
|
+
const tree = new RedBlackTree(entries);
|
|
403
|
+
const deque = new Deque(items);
|
|
404
|
+
const heap = new MaxHeap(items);
|
|
405
|
+
|
|
406
|
+
for (const entry of tree) console.log(entry);
|
|
407
|
+
for (const item of deque) console.log(item);
|
|
408
|
+
for (const item of heap) console.log(item);
|
|
47
409
|
```
|
|
48
410
|
|
|
49
|
-
|
|
411
|
+
---
|
|
50
412
|
|
|
51
|
-
|
|
52
|
-
anymore! JavaScript and TypeScript now have [data-structure-typed]().**`Benchmark`** compared with C++ STL.
|
|
53
|
-
**`API standards`** aligned with ES6 and Java. **`Usability`** is comparable to Python
|
|
413
|
+
## đ All Array Methods Work Everywhere
|
|
54
414
|
|
|
415
|
+
### The Biggest Developer Joy: Array Methods, Everywhere
|
|
55
416
|
|
|
56
|
-
|
|
417
|
+
You know these methods. You use them every day. They work on **every data structure**:
|
|
57
418
|
|
|
58
|
-
|
|
419
|
+
#### Chain on Tree
|
|
59
420
|
|
|
60
|
-
|
|
421
|
+
```typescript
|
|
422
|
+
const rbTree = new RedBlackTree([
|
|
423
|
+
[1, { name: 'Alice', age: 25 }],
|
|
424
|
+
[2, { name: 'Bob', age: 30 }],
|
|
425
|
+
[3, { name: 'Charlie', age: 28 }],
|
|
426
|
+
]);
|
|
61
427
|
|
|
62
|
-
|
|
428
|
+
const result = rbTree
|
|
429
|
+
.filter((value, _key) => (value?.age ?? 0) > 26)
|
|
430
|
+
.map((value, key) => [key, { ...value, id: key }])
|
|
431
|
+
.reduce((sum, value) => sum + (value?.age ?? 0), 0);
|
|
432
|
+
|
|
433
|
+
console.log(result); // 58 â
|
|
434
|
+
```
|
|
435
|
+
|
|
436
|
+
#### Chain on Heap
|
|
437
|
+
|
|
438
|
+
```typescript
|
|
439
|
+
const minHeap = new Heap([
|
|
440
|
+
{ priority: 5, task: 'Email' },
|
|
441
|
+
{ priority: 3, task: 'Chat' },
|
|
442
|
+
{ priority: 8, task: 'Alert' },
|
|
443
|
+
], { comparator: (a, b) => a.priority - b.priority });
|
|
444
|
+
|
|
445
|
+
const urgent = minHeap
|
|
446
|
+
.filter((value, _key) => value.priority > 4)
|
|
447
|
+
.map((value, _key) => value.task);
|
|
448
|
+
|
|
449
|
+
urgent.print(); // ['Alert', 'Email'] â
|
|
450
|
+
```
|
|
63
451
|
|
|
64
|
-
|
|
452
|
+
#### Chain on Deque
|
|
453
|
+
|
|
454
|
+
```typescript
|
|
455
|
+
const deque = new Deque([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
|
|
456
|
+
|
|
457
|
+
const stats = {
|
|
458
|
+
even: deque.filter((value, _key) => value % 2 === 0).toArray(),
|
|
459
|
+
squared: deque.map((value, _key) => value * value).toArray(),
|
|
460
|
+
hasLarge: deque.some((value, _key) => value > 8),
|
|
461
|
+
sum: deque.reduce((acc, value, _key) => acc + value, 0),
|
|
462
|
+
};
|
|
463
|
+
```
|
|
464
|
+
|
|
465
|
+
### Supported Methods Across All Structures
|
|
466
|
+
|
|
467
|
+
| Method | Tree | Heap | Deque | Graph | LinkedList |
|
|
468
|
+
|--------|------|------|-------|-------|------------|
|
|
469
|
+
| map | â
| â
| â
| â
| â
|
|
|
470
|
+
| filter | â
| â
| â
| â
| â
|
|
|
471
|
+
| reduce | â
| â
| â
| â
| â
|
|
|
472
|
+
| find | â
| â
| â
| â
| â
|
|
|
473
|
+
| some/every | â
| â
| â
| â
| â
|
|
|
474
|
+
| keys/values | â
| â
| â
| â
| â
|
|
|
475
|
+
| forEach | â
| â
| â
| â
| â
|
|
|
476
|
+
|
|
477
|
+
---
|
|
478
|
+
|
|
479
|
+
## Why Not Just Use Native JavaScript?
|
|
480
|
+
|
|
481
|
+
### Case 1: Map Doesn't Maintain Sorted Order
|
|
482
|
+
|
|
483
|
+
â Map iteration is insertion order, not key order:
|
|
484
|
+
|
|
485
|
+
```javascript
|
|
486
|
+
const map = new Map([[5, 'E'], [2, 'B'], [8, 'H'], [1, 'A']]);
|
|
487
|
+
for (const [key, value] of map) {
|
|
488
|
+
console.log(key); // 5, 2, 8, 1 (insertion order)
|
|
489
|
+
}
|
|
490
|
+
```
|
|
491
|
+
|
|
492
|
+
â
RedBlackTree maintains sorted order automatically:
|
|
493
|
+
|
|
494
|
+
```javascript
|
|
495
|
+
const tree = new RedBlackTree([[5, 'E'], [2, 'B'], [8, 'H'], [1, 'A']]);
|
|
496
|
+
for (const [key, value] of tree) {
|
|
497
|
+
console.log(key); // 1, 2, 5, 8 (key order) â
|
|
498
|
+
}
|
|
499
|
+
```
|
|
500
|
+
|
|
501
|
+
### Case 2: Array.shift is Too Slow
|
|
502
|
+
|
|
503
|
+
â Array.shift is O(n):
|
|
504
|
+
|
|
505
|
+
```javascript
|
|
506
|
+
const queue = [];
|
|
507
|
+
for (let i = 0; i < 100000; i++) queue.push(i);
|
|
508
|
+
for (let i = 0; i < 100000; i++) queue.shift();
|
|
509
|
+
// Time: 2829ms â
|
|
510
|
+
```
|
|
511
|
+
|
|
512
|
+
â
Deque.shift is O(1):
|
|
513
|
+
|
|
514
|
+
```javascript
|
|
515
|
+
const deque = new Deque();
|
|
516
|
+
for (let i = 0; i < 100000; i++) deque.push(i);
|
|
517
|
+
for (let i = 0; i < 100000; i++) deque.shift();
|
|
518
|
+
// Time: 5.83ms â
|
|
519
|
+
```
|
|
520
|
+
|
|
521
|
+
### Case 3: Maintaining Priority is Manual
|
|
522
|
+
|
|
523
|
+
â Array requires re-sorting O(n log n):
|
|
524
|
+
|
|
525
|
+
```javascript
|
|
526
|
+
const tasks = [];
|
|
527
|
+
function addTask(task) {
|
|
528
|
+
tasks.push(task);
|
|
529
|
+
tasks.sort((a, b) => b.priority - a.priority);
|
|
530
|
+
}
|
|
531
|
+
```
|
|
532
|
+
|
|
533
|
+
â
PriorityQueue maintains priority O(log n):
|
|
534
|
+
|
|
535
|
+
```javascript
|
|
536
|
+
const pq = new MaxPriorityQueue();
|
|
537
|
+
function addTask(task) {
|
|
538
|
+
pq.add(task); // O(log n)
|
|
539
|
+
}
|
|
540
|
+
```
|
|
541
|
+
|
|
542
|
+
### Case 4: Range Queries are Tedious
|
|
543
|
+
|
|
544
|
+
â Array.filter is O(n):
|
|
545
|
+
|
|
546
|
+
```javascript
|
|
547
|
+
const prices = [10, 45, 23, 67, 89, 12, 54, 33, 78];
|
|
548
|
+
const inRange = prices.filter(p => p >= 30 && p <= 70);
|
|
549
|
+
```
|
|
550
|
+
|
|
551
|
+
â
RedBlackTree range queries are O(log n + k):
|
|
552
|
+
|
|
553
|
+
```javascript
|
|
554
|
+
const tree = new RedBlackTree(prices.map((p, i) => [p, i]));
|
|
555
|
+
const inRange = tree.filter((_value, p) => p >= 30 && p <= 70);
|
|
556
|
+
```
|
|
557
|
+
|
|
558
|
+
### Case 5: Prefix Matching is Tedious
|
|
559
|
+
|
|
560
|
+
â Array.filter is O(n*m):
|
|
561
|
+
|
|
562
|
+
```javascript
|
|
563
|
+
const words = ['apple', 'app', 'apply', 'application'];
|
|
564
|
+
const matches = words.filter(w => w.startsWith('app'));
|
|
565
|
+
// For 1M words: checks 1M words â
|
|
566
|
+
```
|
|
567
|
+
|
|
568
|
+
â
Trie prefix matching is O(m + k):
|
|
569
|
+
|
|
570
|
+
```javascript
|
|
571
|
+
const trie = new Trie(words);
|
|
572
|
+
const matches = trie.getWords('appl');
|
|
573
|
+
// O(5 + 4) = 9 operations â
|
|
574
|
+
```
|
|
575
|
+
|
|
576
|
+
---
|
|
577
|
+
|
|
578
|
+
## đ Performance Comparison
|
|
65
579
|
|
|
66
580
|
Performance surpasses that of native JS/TS
|
|
67
581
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
</thead>
|
|
78
|
-
<tbody>
|
|
79
|
-
<tr>
|
|
80
|
-
<td>Queue.push & shift</td>
|
|
81
|
-
<td>5.83 ms</td>
|
|
82
|
-
<td>100K</td>
|
|
83
|
-
<td>Ours</td>
|
|
84
|
-
<td>O(1)</td>
|
|
85
|
-
</tr>
|
|
86
|
-
<tr>
|
|
87
|
-
<td>Array.push & shift</td>
|
|
88
|
-
<td>2829.59 ms</td>
|
|
89
|
-
<td>100K</td>
|
|
90
|
-
<td>Native JS</td>
|
|
91
|
-
<td>O(n)</td>
|
|
92
|
-
</tr>
|
|
93
|
-
<tr>
|
|
94
|
-
<td>Deque.unshift & shift</td>
|
|
95
|
-
<td>2.44 ms</td>
|
|
96
|
-
<td>100K</td>
|
|
97
|
-
<td>Ours</td>
|
|
98
|
-
<td>O(1)</td>
|
|
99
|
-
</tr>
|
|
100
|
-
<tr>
|
|
101
|
-
<td>Array.unshift & shift</td>
|
|
102
|
-
<td>4750.37 ms</td>
|
|
103
|
-
<td>100K</td>
|
|
104
|
-
<td>Native JS</td>
|
|
105
|
-
<td>O(n)</td>
|
|
106
|
-
</tr>
|
|
107
|
-
<tr>
|
|
108
|
-
<td>HashMap.set</td>
|
|
109
|
-
<td>122.51 ms</td>
|
|
110
|
-
<td>1M</td>
|
|
111
|
-
<td>Ours</td>
|
|
112
|
-
<td>O(1)</td>
|
|
113
|
-
</tr>
|
|
114
|
-
<tr>
|
|
115
|
-
<td>Map.set</td>
|
|
116
|
-
<td>223.80 ms</td>
|
|
117
|
-
<td>1M</td>
|
|
118
|
-
<td>Native JS</td>
|
|
119
|
-
<td>O(1)</td>
|
|
120
|
-
</tr>
|
|
121
|
-
<tr>
|
|
122
|
-
<td>Set.add</td>
|
|
123
|
-
<td>185.06 ms</td>
|
|
124
|
-
<td>1M</td>
|
|
125
|
-
<td>Native JS</td>
|
|
126
|
-
<td>O(1)</td>
|
|
127
|
-
</tr>
|
|
128
|
-
</tbody>
|
|
129
|
-
</table>
|
|
582
|
+
| Method | Time Taken | Data Scale | Belongs To | Big O |
|
|
583
|
+
|--------|-----------|-----------|-----------|-------|
|
|
584
|
+
| Queue.push & shift | 5.83 ms | 100K | Ours | O(1) |
|
|
585
|
+
| Array.push & shift | 2829.59 ms | 100K | Native JS | O(n) |
|
|
586
|
+
| Deque.unshift & shift | 2.44 ms | 100K | Ours | O(1) |
|
|
587
|
+
| Array.unshift & shift | 4750.37 ms | 100K | Native JS | O(n) |
|
|
588
|
+
| HashMap.set | 122.51 ms | 1M | Ours | O(1) |
|
|
589
|
+
| Map.set | 223.80 ms | 1M | Native JS | O(1) |
|
|
590
|
+
| Set.add | 185.06 ms | 1M | Native JS | O(1) |
|
|
130
591
|
|
|
131
|
-
###
|
|
592
|
+
### Benchmark
|
|
132
593
|
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
594
|
+
MacBook Pro (15-inch, 2018)
|
|
595
|
+
|
|
596
|
+
Processor 2.2 GHz 6-Core Intel Core i7
|
|
597
|
+
|
|
598
|
+
Memory 16 GB 2400 MHz DDR4
|
|
599
|
+
|
|
600
|
+
Graphics Radeon Pro 555X 4 GB
|
|
601
|
+
|
|
602
|
+
Intel UHD Graphics 630 1536 MB
|
|
603
|
+
|
|
604
|
+
macOS Sequoia 15.7.2
|
|
605
|
+
|
|
606
|
+
### Performance & Runtime Compatibility
|
|
607
|
+
|
|
608
|
+
[//]: # (No deletion!!! Start of Replace Section)
|
|
609
|
+
|
|
610
|
+
<h2>red-black-tree</h2><table><thead><tr><th>test name</th><th>time taken (ms)</th><th>sample mean (secs)</th><th>sample deviation</th></tr></thead><tbody><tr><td>1,000,000 add</td><td>410.34</td><td>0.41</td><td>0.01</td></tr><tr><td>1,000,000 get</td><td>5.20</td><td>0.01</td><td>8.16e-5</td></tr><tr><td>1,000,000 iterator</td><td>154.25</td><td>0.15</td><td>0.02</td></tr><tr><td>CPT 1,000,000 add</td><td>656.43</td><td>0.66</td><td>0.00</td></tr><tr><td>CPT 1,000,000 add</td><td>684.17</td><td>0.68</td><td>0.01</td></tr></tbody></table><h2>queue</h2><table><thead><tr><th>test name</th><th>time taken (ms)</th><th>sample mean (secs)</th><th>sample deviation</th></tr></thead><tbody><tr><td>1,000,000 push</td><td>26.97</td><td>0.03</td><td>0.00</td></tr><tr><td>100,000 push & shift</td><td>2.87</td><td>0.00</td><td>2.71e-4</td></tr><tr><td>Native JS Array 100,000 push & shift</td><td>1120.94</td><td>1.12</td><td>0.20</td></tr></tbody></table><h2>deque</h2><table><thead><tr><th>test name</th><th>time taken (ms)</th><th>sample mean (secs)</th><th>sample deviation</th></tr></thead><tbody><tr><td>1,000,000 push</td><td>8.75</td><td>0.01</td><td>6.99e-4</td></tr><tr><td>1,000,000 push & pop</td><td>12.95</td><td>0.01</td><td>4.21e-4</td></tr><tr><td>1,000,000 push & shift</td><td>13.73</td><td>0.01</td><td>4.53e-4</td></tr><tr><td>100,000 push & shift</td><td>1.36</td><td>0.00</td><td>5.42e-5</td></tr><tr><td>Native JS Array 100,000 push & shift</td><td>1167.06</td><td>1.17</td><td>0.26</td></tr><tr><td>100,000 unshift & shift</td><td>1.31</td><td>0.00</td><td>4.73e-5</td></tr><tr><td>Native JS Array 100,000 unshift & shift</td><td>1911.47</td><td>1.91</td><td>0.02</td></tr></tbody></table><h2>heap</h2><table><thead><tr><th>test name</th><th>time taken (ms)</th><th>sample mean (secs)</th><th>sample deviation</th></tr></thead><tbody><tr><td>100,000 add</td><td>4.60</td><td>0.00</td><td>1.07e-4</td></tr><tr><td>100,000 add & poll</td><td>16.96</td><td>0.02</td><td>3.45e-4</td></tr></tbody></table><h2>avl-tree</h2><table><thead><tr><th>test name</th><th>time taken (ms)</th><th>sample mean (secs)</th><th>sample deviation</th></tr></thead><tbody><tr><td>100,000 add randomly</td><td>324.51</td><td>0.32</td><td>0.01</td></tr><tr><td>100,000 add</td><td>299.76</td><td>0.30</td><td>0.02</td></tr><tr><td>100,000 get</td><td>0.26</td><td>2.58e-4</td><td>3.65e-6</td></tr><tr><td>100,000 getNode</td><td>169.33</td><td>0.17</td><td>0.00</td></tr><tr><td>100,000 iterator</td><td>14.43</td><td>0.01</td><td>0.00</td></tr><tr><td>100,000 add & delete orderly</td><td>434.44</td><td>0.43</td><td>0.01</td></tr><tr><td>100,000 add & delete randomly</td><td>541.78</td><td>0.54</td><td>0.01</td></tr></tbody></table><h2>hash-map</h2><table><thead><tr><th>test name</th><th>time taken (ms)</th><th>sample mean (secs)</th><th>sample deviation</th></tr></thead><tbody><tr><td>1,000,000 set</td><td>43.23</td><td>0.04</td><td>0.01</td></tr><tr><td>Native JS Map 1,000,000 set</td><td>147.12</td><td>0.15</td><td>0.01</td></tr><tr><td>Native JS Set 1,000,000 add</td><td>116.18</td><td>0.12</td><td>0.01</td></tr><tr><td>1,000,000 set & get</td><td>46.39</td><td>0.05</td><td>0.01</td></tr><tr><td>Native JS Map 1,000,000 set & get</td><td>196.92</td><td>0.20</td><td>0.01</td></tr><tr><td>Native JS Set 1,000,000 add & has</td><td>163.92</td><td>0.16</td><td>0.01</td></tr><tr><td>1,000,000 ObjKey set & get</td><td>243.36</td><td>0.24</td><td>0.03</td></tr><tr><td>Native JS Map 1,000,000 ObjKey set & get</td><td>211.66</td><td>0.21</td><td>0.02</td></tr><tr><td>Native JS Set 1,000,000 ObjKey add & has</td><td>196.57</td><td>0.20</td><td>0.01</td></tr></tbody></table><h2>directed-graph</h2><table><thead><tr><th>test name</th><th>time taken (ms)</th><th>sample mean (secs)</th><th>sample deviation</th></tr></thead><tbody><tr><td>1,000 addVertex</td><td>0.05</td><td>4.60e-5</td><td>6.59e-7</td></tr><tr><td>1,000 addEdge</td><td>3.02</td><td>0.00</td><td>2.85e-4</td></tr><tr><td>1,000 getVertex</td><td>0.04</td><td>3.77e-5</td><td>4.66e-7</td></tr><tr><td>1,000 getEdge</td><td>41.48</td><td>0.04</td><td>0.01</td></tr><tr><td>tarjan</td><td>240.33</td><td>0.24</td><td>0.01</td></tr><tr><td>topologicalSort</td><td>195.62</td><td>0.20</td><td>0.01</td></tr></tbody></table><h2>trie</h2><table><thead><tr><th>test name</th><th>time taken (ms)</th><th>sample mean (secs)</th><th>sample deviation</th></tr></thead><tbody><tr><td>100,000 push</td><td>27.15</td><td>0.03</td><td>6.61e-4</td></tr><tr><td>100,000 getWords</td><td>41.18</td><td>0.04</td><td>0.00</td></tr></tbody></table><h2>stack</h2><table><thead><tr><th>test name</th><th>time taken (ms)</th><th>sample mean (secs)</th><th>sample deviation</th></tr></thead><tbody><tr><td>1,000,000 push</td><td>25.21</td><td>0.03</td><td>0.00</td></tr><tr><td>1,000,000 push & pop</td><td>29.12</td><td>0.03</td><td>0.00</td></tr></tbody></table>
|
|
611
|
+
|
|
612
|
+
[//]: # (No deletion!!! End of Replace Section)
|
|
613
|
+
|
|
614
|
+
---
|
|
615
|
+
|
|
616
|
+
## đ Plain Language Explanations
|
|
617
|
+
|
|
618
|
+
For those who love understanding concepts through metaphors:
|
|
619
|
+
|
|
620
|
+
| Data Structure | Plain Language Definition | Example |
|
|
621
|
+
|---|---|---|
|
|
622
|
+
| **Linked List** | A line of bunnies, where each bunny holds the tail of the bunny in front (each bunny only knows the bunny behind). Search takes O(n) time but insertion is O(1). | To find bunny "Pablo", start from the first bunny and follow tails until found |
|
|
623
|
+
| **Array** | A line of numbered bunnies. You can find bunny #680 directly (O(1)), but inserting a bunny requires renumbering all bunnies behind it (O(n)). | Finding element by index is instant, but inserting in the middle is slow |
|
|
624
|
+
| **Queue** | A line of numbered bunnies with a sticky note on the first bunny. Removing from front only moves the sticky note (O(1)), without renumbering. Adding to the tail gives new numbers (O(1)). | Process items in FIFO order, efficiently from both ends |
|
|
625
|
+
| **Deque** | A line of grouped, numbered bunnies with a sticky note. Remove from front by moving sticky note (O(1)). When a group is exhausted, renumber only that group. Tail handled similarly. | Efficient removal/insertion from both ends with batching optimization |
|
|
626
|
+
| **Stack** | A line of bunnies in a dead-end tunnel. Add/remove only at the entrance/end. | Process items in LIFO order |
|
|
627
|
+
| **Binary Tree** | A tree where each node (bunny) has at most two children. When you add sorted data like [4,2,6,1,3,5,7], it forms a complete binary tree. | Hierarchical organization of data |
|
|
628
|
+
| **Binary Search Tree** | Disciplined bunnies arranged by order: all left subtree values < node < all right subtree values. This maintains O(log n) for search/insert/delete. | Find items exponentially faster than linear search |
|
|
629
|
+
| **Red-Black Tree** | A self-balancing binary search tree where nodes are marked red/black to ensure no path is twice as long as another. | Maintains O(log n) guarantees automatically |
|
|
630
|
+
| **AVL Tree** | A strictly balanced binary search tree where every node's left/right subtrees differ by at most 1 in height. Provides highest search efficiency but slower insertions/deletions. | Maximum search speed with strict balance |
|
|
631
|
+
| **Heap** | A special complete binary tree stored in an array. Parent at index i has children at 2i+1 and 2i+2. | Efficient priority queue implementation |
|
|
632
|
+
| **Trie** | A tree where each node represents a character. Path from root to node spells a word. | Prefix search in O(m + k) time instead of O(n*m) |
|
|
633
|
+
| **Graph** | A network of connected bunnies. Directed: each bunny points to specific other bunnies. Undirected: mutual connections. | Model relationships, networks, dependencies |
|
|
634
|
+
|
|
635
|
+
|
|
636
|
+
---
|
|
637
|
+
|
|
638
|
+
## đģ Code Snippets: Patterns & Examples
|
|
639
|
+
|
|
640
|
+
### Pattern 1: Interoperability & Iterator Conversion
|
|
641
|
+
|
|
642
|
+
```typescript
|
|
643
|
+
import { RedBlackTree } from 'data-structure-typed';
|
|
644
|
+
|
|
645
|
+
const numbers = [6, 1, 2, 7, 5, 3, 4, 9, 8];
|
|
646
|
+
|
|
647
|
+
// Create sorted tree
|
|
648
|
+
const tree = new RedBlackTree(numbers);
|
|
649
|
+
|
|
650
|
+
// Convert to array (spread operator)
|
|
651
|
+
const sorted = [...tree];
|
|
652
|
+
console.log(sorted); // [1, 2, 3, 4, 5, 6, 7, 8, 9]
|
|
653
|
+
|
|
654
|
+
// Iterate with for...of
|
|
655
|
+
for (const item of tree) {
|
|
656
|
+
console.log(item);
|
|
657
|
+
}
|
|
658
|
+
|
|
659
|
+
// Get keys/values separately
|
|
660
|
+
const keys = [...tree.keys()];
|
|
661
|
+
const values = [...tree.values()];
|
|
662
|
+
|
|
663
|
+
// Destructuring works
|
|
664
|
+
const [first, second, ...rest] = tree;
|
|
665
|
+
|
|
666
|
+
// Works with native JavaScript
|
|
667
|
+
const json = JSON.stringify([...tree]);
|
|
668
|
+
const set = new Set(tree.keys());
|
|
669
|
+
```
|
|
670
|
+
|
|
671
|
+
### Pattern 2: Method Chaining on Exotic Structures
|
|
672
|
+
|
|
673
|
+
â Before (Array with shift):
|
|
674
|
+
|
|
675
|
+
```javascript
|
|
676
|
+
const queue = [1, 2, 3, 4, 5];
|
|
677
|
+
for (let i = 0; i < 100000; i++) {
|
|
678
|
+
queue.shift(); // O(n)
|
|
679
|
+
}
|
|
680
|
+
```
|
|
681
|
+
|
|
682
|
+
â
After (Deque):
|
|
683
|
+
|
|
684
|
+
```javascript
|
|
685
|
+
import { Deque } from 'data-structure-typed';
|
|
686
|
+
|
|
687
|
+
const deque = new Deque([1, 2, 3, 4, 5]);
|
|
688
|
+
for (let i = 0; i < 100000; i++) {
|
|
689
|
+
deque.shift(); // O(1)
|
|
690
|
+
}
|
|
691
|
+
```
|
|
692
|
+
|
|
693
|
+
### Pattern 3: Seamless Structure Conversion
|
|
694
|
+
|
|
695
|
+
```typescript
|
|
696
|
+
import { RedBlackTree, MaxHeap, Deque } from 'data-structure-typed';
|
|
697
|
+
|
|
698
|
+
const data = [64, 34, 25, 12, 22, 11, 90];
|
|
699
|
+
|
|
700
|
+
// Array â Tree for sorting
|
|
701
|
+
const tree = new RedBlackTree(data);
|
|
702
|
+
console.log([...tree.keys()]); // [11, 12, 22, 25, 34, 64, 90]
|
|
703
|
+
|
|
704
|
+
// Tree â Heap for priority
|
|
705
|
+
const heap = new MaxHeap([...tree.keys()]);
|
|
706
|
+
|
|
707
|
+
// Heap â Deque for queue operations
|
|
708
|
+
const deque = new Deque([...heap]);
|
|
709
|
+
|
|
710
|
+
// Back to Array for final output
|
|
711
|
+
const result = [...deque];
|
|
712
|
+
```
|
|
713
|
+
|
|
714
|
+
### Pattern 4: Query and Analysis
|
|
715
|
+
|
|
716
|
+
#### Tree Example
|
|
717
|
+
|
|
718
|
+
```typescript
|
|
719
|
+
const tree = new RedBlackTree<number, { name: string; score: number }>();
|
|
720
|
+
tree.add(1, { name: 'Alice', score: 95 });
|
|
721
|
+
tree.add(2, { name: 'Bob', score: 87 });
|
|
722
|
+
tree.add(3, { name: 'Charlie', score: 92 });
|
|
723
|
+
|
|
724
|
+
const totalHighScore = tree
|
|
725
|
+
.filter((value, _key) => (value?.score ?? 0) >= 85)
|
|
726
|
+
.map((value, key) => [key, value?.score ?? 0])
|
|
727
|
+
.reduce((sum, score) => sum + (score ?? 0), 0);
|
|
728
|
+
|
|
729
|
+
console.log(totalHighScore); // 274
|
|
730
|
+
```
|
|
731
|
+
|
|
732
|
+
#### Heap Example
|
|
733
|
+
|
|
734
|
+
```typescript
|
|
735
|
+
const heap = new MaxHeap([
|
|
736
|
+
{ priority: 5, task: 'Email' },
|
|
737
|
+
{ priority: 8, task: 'Alert' },
|
|
738
|
+
], { comparator: (a, b) => b.priority - a.priority });
|
|
739
|
+
|
|
740
|
+
const urgentTasks = heap
|
|
741
|
+
.filter((value, _key) => value.priority >= 8)
|
|
742
|
+
.map((value, _key) => [value.priority, value.task]);
|
|
743
|
+
```
|
|
744
|
+
|
|
745
|
+
#### Deque Example
|
|
746
|
+
|
|
747
|
+
```typescript
|
|
748
|
+
const deque = new Deque<number>([1, 2, 3, 4, 5]);
|
|
749
|
+
|
|
750
|
+
const evenSum = deque
|
|
751
|
+
.filter((value, _key) => value % 2 === 0)
|
|
752
|
+
.map((value, _key) => value * 2)
|
|
753
|
+
.reduce((sum, value) => sum + value, 0);
|
|
754
|
+
```
|
|
755
|
+
|
|
756
|
+
---
|
|
757
|
+
|
|
758
|
+
## đ CRUD Operations: Basic Usage Examples
|
|
759
|
+
|
|
760
|
+
### Red Black Tree CRUD
|
|
761
|
+
|
|
762
|
+
#### TS
|
|
763
|
+
|
|
764
|
+
```ts
|
|
765
|
+
import { RedBlackTree } from 'data-structure-typed';
|
|
766
|
+
|
|
767
|
+
const rbTree = new RedBlackTree<number>();
|
|
768
|
+
|
|
769
|
+
// CREATE: Add elements
|
|
770
|
+
rbTree.add(11);
|
|
771
|
+
rbTree.add(3);
|
|
772
|
+
rbTree.addMany([15, 1, 8, 13, 16, 2, 6, 9, 12, 14, 4, 7, 10, 5]);
|
|
773
|
+
|
|
774
|
+
// READ: Query elements
|
|
775
|
+
rbTree.has(6); // true
|
|
776
|
+
rbTree.size === 16; // true
|
|
777
|
+
const node6 = rbTree.getNode(6); // BSTNode
|
|
778
|
+
rbTree.getHeight(6) === 2; // true (height of node with key 6)
|
|
779
|
+
rbTree.getHeight() === 5; // true (tree height)
|
|
780
|
+
|
|
781
|
+
// UPDATE: Delete elements
|
|
782
|
+
rbTree.delete(6);
|
|
783
|
+
rbTree.get(6); // undefined
|
|
784
|
+
|
|
785
|
+
// Query after update
|
|
786
|
+
rbTree.getLeftMost()?.key === 1; // true
|
|
787
|
+
rbTree.isAVLBalanced(); // true
|
|
788
|
+
|
|
789
|
+
rbTree.print()
|
|
790
|
+
// ______________11_____
|
|
791
|
+
// / \
|
|
792
|
+
// ___3_______ _13_____
|
|
793
|
+
// / \ / \
|
|
794
|
+
// 1_ _____8____ 12 _15__
|
|
795
|
+
// \ / \ / \
|
|
796
|
+
// 2 4_ _10 14 16
|
|
797
|
+
// \ /
|
|
798
|
+
// 5_ 9
|
|
799
|
+
// \
|
|
800
|
+
// 7
|
|
801
|
+
```
|
|
802
|
+
|
|
803
|
+
#### JS
|
|
804
|
+
|
|
805
|
+
```js
|
|
806
|
+
import { RedBlackTree } from 'data-structure-typed';
|
|
807
|
+
|
|
808
|
+
const rbTree = new RedBlackTree();
|
|
809
|
+
|
|
810
|
+
// CREATE
|
|
811
|
+
rbTree.addMany([11, 3, 15, 1, 8, 13, 16, 2, 6, 9, 12, 14, 4, 7, 10, 5]);
|
|
812
|
+
|
|
813
|
+
// READ
|
|
814
|
+
rbTree.has(6); // true
|
|
815
|
+
const height = rbTree.getHeight(); // 5
|
|
816
|
+
|
|
817
|
+
// UPDATE
|
|
818
|
+
rbTree.delete(10);
|
|
819
|
+
rbTree.isAVLBalanced(); // true
|
|
820
|
+
|
|
821
|
+
// PRINT
|
|
822
|
+
rbTree.print();
|
|
823
|
+
```
|
|
824
|
+
|
|
825
|
+
### BST CRUD with Custom Objects
|
|
826
|
+
|
|
827
|
+
```ts
|
|
828
|
+
import { BST, BSTNode } from 'data-structure-typed';
|
|
829
|
+
|
|
830
|
+
const bst = new BST<number, { height: number, age: number }>();
|
|
831
|
+
|
|
832
|
+
// CREATE
|
|
833
|
+
bst.add(11, { "name": "Pablo", "size": 15 });
|
|
834
|
+
bst.add(3, { "name": "Kirk", "size": 1 });
|
|
835
|
+
|
|
836
|
+
bst.addMany(
|
|
837
|
+
[15, 1, 8, 13, 16, 2, 6, 9, 12, 14, 4, 7, 10, 5],
|
|
838
|
+
[
|
|
839
|
+
{ "name": "Alice", "size": 15 },
|
|
840
|
+
{ "name": "Bob", "size": 1 },
|
|
841
|
+
{ "name": "Charlie", "size": 8 },
|
|
842
|
+
{ "name": "David", "size": 13 },
|
|
843
|
+
{ "name": "Emma", "size": 16 },
|
|
844
|
+
{ "name": "Frank", "size": 2 },
|
|
845
|
+
{ "name": "Grace", "size": 6 },
|
|
846
|
+
{ "name": "Hannah", "size": 9 },
|
|
847
|
+
{ "name": "Isaac", "size": 12 },
|
|
848
|
+
{ "name": "Jack", "size": 14 },
|
|
849
|
+
{ "name": "Katie", "size": 4 },
|
|
850
|
+
{ "name": "Liam", "size": 7 },
|
|
851
|
+
{ "name": "Mia", "size": 10 },
|
|
852
|
+
{ "name": "Noah", "size": 5 }
|
|
853
|
+
]
|
|
854
|
+
);
|
|
855
|
+
|
|
856
|
+
// READ
|
|
857
|
+
const value = bst.get(11); // { "name": "Pablo", "size": 15 }
|
|
858
|
+
const has11 = bst.has(11); // true
|
|
859
|
+
|
|
860
|
+
// UPDATE
|
|
861
|
+
bst.delete(11);
|
|
862
|
+
|
|
863
|
+
// VERIFY
|
|
864
|
+
const afterDelete = bst.has(11); // false
|
|
865
|
+
```
|
|
866
|
+
|
|
867
|
+
### Queue/Deque CRUD
|
|
868
|
+
|
|
869
|
+
```ts
|
|
870
|
+
import { Queue, Deque } from 'data-structure-typed';
|
|
871
|
+
|
|
872
|
+
const queue = new Queue([1, 2, 3, 4, 5]);
|
|
873
|
+
|
|
874
|
+
// CREATE/ADD
|
|
875
|
+
queue.push(6); // O(1)
|
|
876
|
+
|
|
877
|
+
// READ
|
|
878
|
+
const front = queue.peek(); // 1
|
|
879
|
+
const size = queue.size; // 6
|
|
880
|
+
|
|
881
|
+
// REMOVE
|
|
882
|
+
const removed = queue.shift(); // O(1) - removes 1
|
|
883
|
+
queue.pop(); // O(1) - removes last
|
|
884
|
+
|
|
885
|
+
// Same API for Deque
|
|
886
|
+
const deque = new Deque([1, 2, 3, 4, 5]);
|
|
887
|
+
deque.push(6);
|
|
888
|
+
deque.unshift(0); // Add to front
|
|
889
|
+
deque.pop(); // Remove from end
|
|
890
|
+
deque.shift(); // Remove from front
|
|
891
|
+
```
|
|
892
|
+
|
|
893
|
+
### Graph CRUD
|
|
894
|
+
|
|
895
|
+
```ts
|
|
896
|
+
import { DirectedGraph } from 'data-structure-typed';
|
|
897
|
+
|
|
898
|
+
const graph = new DirectedGraph<string>();
|
|
899
|
+
|
|
900
|
+
// CREATE
|
|
901
|
+
graph.addVertex('A');
|
|
902
|
+
graph.addVertex('B');
|
|
903
|
+
graph.addVertex('C');
|
|
904
|
+
|
|
905
|
+
// CONNECT
|
|
906
|
+
graph.addEdge('A', 'B');
|
|
907
|
+
graph.addEdge('B', 'C');
|
|
908
|
+
graph.addEdge('A', 'C');
|
|
909
|
+
|
|
910
|
+
// READ
|
|
911
|
+
graph.hasVertex('A'); // true
|
|
912
|
+
graph.hasEdge('A', 'B'); // true
|
|
913
|
+
const neighbors = graph.getNeighbors('A'); // ['B', 'C']
|
|
914
|
+
|
|
915
|
+
// UPDATE
|
|
916
|
+
graph.deleteEdgeSrcToDest('A', 'C');
|
|
917
|
+
graph.hasEdge('A', 'C'); // false
|
|
918
|
+
|
|
919
|
+
// ALGORITHMS
|
|
920
|
+
const topologicalOrder = graph.topologicalSort();
|
|
921
|
+
const { minDist, minPath } = graph.dijkstra('A', 'C');
|
|
922
|
+
```
|
|
923
|
+
|
|
924
|
+
---
|
|
925
|
+
|
|
926
|
+
## đ Real-World Examples: Production Code
|
|
927
|
+
|
|
928
|
+
### Example 1: Message Queue - Order Processing
|
|
929
|
+
|
|
930
|
+
```typescript
|
|
931
|
+
import { Deque } from 'data-structure-typed';
|
|
932
|
+
|
|
933
|
+
interface Order {
|
|
934
|
+
id: string;
|
|
935
|
+
customerId: string;
|
|
936
|
+
priority: 'normal' | 'urgent';
|
|
937
|
+
}
|
|
938
|
+
|
|
939
|
+
class OrderProcessor {
|
|
940
|
+
private normalQueue = new Deque<Order>();
|
|
941
|
+
private urgentQueue = new Deque<Order>();
|
|
942
|
+
private running = false;
|
|
943
|
+
|
|
944
|
+
constructor(private readonly urgentBurst: number = 5) {}
|
|
945
|
+
|
|
946
|
+
addOrder(order: Order): void {
|
|
947
|
+
if (order.priority === 'urgent') {
|
|
948
|
+
this.urgentQueue.push(order);
|
|
949
|
+
} else {
|
|
950
|
+
this.normalQueue.push(order);
|
|
951
|
+
}
|
|
952
|
+
void this.processOrders();
|
|
953
|
+
}
|
|
954
|
+
|
|
955
|
+
async processOrders(): Promise<void> {
|
|
956
|
+
if (this.running) return;
|
|
957
|
+
this.running = true;
|
|
958
|
+
|
|
959
|
+
try {
|
|
960
|
+
let urgentStreak = 0;
|
|
961
|
+
|
|
962
|
+
while (!this.urgentQueue.isEmpty() || !this.normalQueue.isEmpty()) {
|
|
963
|
+
const shouldTakeUrgent =
|
|
964
|
+
!this.urgentQueue.isEmpty() &&
|
|
965
|
+
(urgentStreak < this.urgentBurst || this.normalQueue.isEmpty());
|
|
966
|
+
|
|
967
|
+
const order = shouldTakeUrgent ? this.urgentQueue.shift() : this.normalQueue.shift();
|
|
968
|
+
if (!order) continue;
|
|
969
|
+
|
|
970
|
+
urgentStreak = order.priority === 'urgent' ? urgentStreak + 1 : 0;
|
|
971
|
+
|
|
972
|
+
try {
|
|
973
|
+
await this.processOrder(order);
|
|
974
|
+
} catch (err) {
|
|
975
|
+
console.error(`FAILED`, order.id, err);
|
|
976
|
+
}
|
|
977
|
+
}
|
|
978
|
+
} finally {
|
|
979
|
+
this.running = false;
|
|
980
|
+
}
|
|
981
|
+
}
|
|
982
|
+
|
|
983
|
+
private async processOrder(order: Order): Promise<void> {
|
|
984
|
+
await new Promise<void>(r => setTimeout(r, 10));
|
|
985
|
+
console.log(
|
|
986
|
+
`OK [${order.priority.toUpperCase()}] order:${order.id} customer:${order.customerId}`
|
|
987
|
+
);
|
|
988
|
+
}
|
|
989
|
+
}
|
|
990
|
+
```
|
|
991
|
+
|
|
992
|
+
### Example 2: LRU Cache
|
|
993
|
+
|
|
994
|
+
```typescript
|
|
995
|
+
class LRUCache<T> {
|
|
996
|
+
private cache = new DoublyLinkedList<[string, T]>();
|
|
997
|
+
private map = new Map<string, any>();
|
|
998
|
+
private maxSize = 100;
|
|
999
|
+
|
|
1000
|
+
get(key: string): T | null {
|
|
1001
|
+
const node = this.map.get(key);
|
|
1002
|
+
if (!node) return null;
|
|
1003
|
+
|
|
1004
|
+
this.cache.delete(node);
|
|
1005
|
+
const newNode = this.cache.push(key, node.value[1]);
|
|
1006
|
+
this.map.set(key, newNode);
|
|
1007
|
+
return node.value[1];
|
|
1008
|
+
}
|
|
1009
|
+
|
|
1010
|
+
set(key: string, value: T): void {
|
|
1011
|
+
if (this.map.has(key)) {
|
|
1012
|
+
const node = this.map.get(key)!;
|
|
1013
|
+
this.cache.delete(node);
|
|
1014
|
+
}
|
|
1015
|
+
|
|
1016
|
+
const node = this.cache.push(key, value);
|
|
1017
|
+
this.map.set(key, node);
|
|
1018
|
+
|
|
1019
|
+
if (this.cache.length > this.maxSize) {
|
|
1020
|
+
const oldest = this.cache.shift();
|
|
1021
|
+
if (oldest) {
|
|
1022
|
+
this.map.delete(oldest[0]);
|
|
1023
|
+
}
|
|
1024
|
+
}
|
|
1025
|
+
}
|
|
1026
|
+
}
|
|
1027
|
+
|
|
1028
|
+
// Why DoublyLinkedList?
|
|
1029
|
+
// - O(1) delete from any position
|
|
1030
|
+
// - O(1) push to end
|
|
1031
|
+
// - Perfect for LRU implementation
|
|
1032
|
+
```
|
|
1033
|
+
|
|
1034
|
+
### Example 3: Leaderboard System
|
|
1035
|
+
|
|
1036
|
+
```typescript
|
|
1037
|
+
import { RedBlackTree } from 'data-structure-typed';
|
|
1038
|
+
|
|
1039
|
+
interface Player {
|
|
1040
|
+
id: string;
|
|
1041
|
+
name: string;
|
|
1042
|
+
score: number;
|
|
1043
|
+
}
|
|
1044
|
+
|
|
1045
|
+
class Leaderboard {
|
|
1046
|
+
private scoreTree = new RedBlackTree<number, Player>();
|
|
1047
|
+
private playerMap = new Map<string, number>();
|
|
1048
|
+
|
|
1049
|
+
updateScore(playerId: string, newScore: number): void {
|
|
1050
|
+
if (this.playerMap.has(playerId)) {
|
|
1051
|
+
const oldScore = this.playerMap.get(playerId)!;
|
|
1052
|
+
this.scoreTree.delete(oldScore);
|
|
1053
|
+
}
|
|
1054
|
+
|
|
1055
|
+
const player: Player = { id: playerId, name: playerId, score: newScore };
|
|
1056
|
+
this.scoreTree.add(newScore, player);
|
|
1057
|
+
this.playerMap.set(playerId, newScore);
|
|
1058
|
+
}
|
|
1059
|
+
|
|
1060
|
+
getTopN(n: number): Player[] {
|
|
1061
|
+
return [...this.scoreTree.values()].reverse().slice(0, n) as Player[];
|
|
1062
|
+
}
|
|
1063
|
+
|
|
1064
|
+
getRank(playerId: string): number | null {
|
|
1065
|
+
const score = this.playerMap.get(playerId);
|
|
1066
|
+
if (score === undefined) return null;
|
|
1067
|
+
|
|
1068
|
+
const higherScores = [...this.scoreTree.keys()].filter(s => s > score).length;
|
|
1069
|
+
return higherScores + 1;
|
|
1070
|
+
}
|
|
1071
|
+
}
|
|
1072
|
+
|
|
1073
|
+
// Why RedBlackTree?
|
|
1074
|
+
// - Automatically maintains sorted order
|
|
1075
|
+
// - O(log n) insertions and deletions
|
|
1076
|
+
// - O(log n) searches
|
|
1077
|
+
// - Perfect for real-time rankings
|
|
1078
|
+
```
|
|
1079
|
+
|
|
1080
|
+
### Example 4: Task Scheduler with Priority Queue
|
|
1081
|
+
|
|
1082
|
+
```typescript
|
|
1083
|
+
import { MaxPriorityQueue } from 'data-structure-typed';
|
|
1084
|
+
|
|
1085
|
+
interface Task {
|
|
1086
|
+
id: string;
|
|
1087
|
+
priority: number;
|
|
1088
|
+
action: () => Promise<void>;
|
|
1089
|
+
}
|
|
1090
|
+
|
|
1091
|
+
class TaskScheduler {
|
|
1092
|
+
private maxPQ = new MaxPriorityQueue<Task>([], {
|
|
1093
|
+
comparator: (a, b) => b.priority - a.priority,
|
|
1094
|
+
});
|
|
1095
|
+
|
|
1096
|
+
addTask(task: Task): void {
|
|
1097
|
+
this.maxPQ.add(task);
|
|
1098
|
+
}
|
|
1099
|
+
|
|
1100
|
+
async start(): Promise<void> {
|
|
1101
|
+
while (!this.maxPQ.isEmpty()) {
|
|
1102
|
+
const task = this.maxPQ.poll();
|
|
1103
|
+
if (!task) break;
|
|
1104
|
+
|
|
1105
|
+
try {
|
|
1106
|
+
await task.action();
|
|
1107
|
+
console.log(`Task ${task.id} completed (priority: ${task.priority})`);
|
|
1108
|
+
} catch (error) {
|
|
1109
|
+
console.error(`Task ${task.id} failed (priority: ${task.priority}):`, error);
|
|
1110
|
+
}
|
|
1111
|
+
}
|
|
1112
|
+
}
|
|
1113
|
+
}
|
|
1114
|
+
```
|
|
1115
|
+
|
|
1116
|
+
### Example 5: Search Index - Autocomplete
|
|
1117
|
+
|
|
1118
|
+
```typescript
|
|
1119
|
+
import { Trie } from 'data-structure-typed';
|
|
1120
|
+
|
|
1121
|
+
class SearchIndex {
|
|
1122
|
+
private trie = new Trie();
|
|
1123
|
+
|
|
1124
|
+
indexDocument(docId: number, content: string): void {
|
|
1125
|
+
const words = content.toLowerCase().split(/\s+/);
|
|
1126
|
+
|
|
1127
|
+
for (const word of words) {
|
|
1128
|
+
const existing = this.trie.get(word);
|
|
1129
|
+
if (!existing) {
|
|
1130
|
+
this.trie.set(word, [docId]);
|
|
1131
|
+
} else {
|
|
1132
|
+
if (!existing.includes(docId)) {
|
|
1133
|
+
existing.push(docId);
|
|
1134
|
+
}
|
|
1135
|
+
this.trie.set(word, existing);
|
|
1136
|
+
}
|
|
1137
|
+
}
|
|
1138
|
+
}
|
|
1139
|
+
|
|
1140
|
+
autocomplete(prefix: string): string[] {
|
|
1141
|
+
return this.trie.getWordsWithPrefix(prefix.toLowerCase());
|
|
1142
|
+
}
|
|
1143
|
+
|
|
1144
|
+
search(word: string): number[] {
|
|
1145
|
+
return this.trie.get(word.toLowerCase()) ?? [];
|
|
1146
|
+
}
|
|
1147
|
+
}
|
|
1148
|
+
|
|
1149
|
+
// Why Trie?
|
|
1150
|
+
// - O(m + k) prefix search (m = prefix length, k = results)
|
|
1151
|
+
// - Perfect for autocomplete
|
|
1152
|
+
// - Scales to millions of words
|
|
1153
|
+
```
|
|
1154
|
+
|
|
1155
|
+
---
|
|
1156
|
+
|
|
1157
|
+
## đ Migration Guide: From Native JS
|
|
1158
|
+
|
|
1159
|
+
### Pattern 1: Replacing Array.shift with Deque
|
|
1160
|
+
|
|
1161
|
+
â Before:
|
|
1162
|
+
|
|
1163
|
+
```javascript
|
|
1164
|
+
const queue = [1, 2, 3, 4, 5];
|
|
1165
|
+
for (let i = 0; i < 100000; i++) {
|
|
1166
|
+
queue.shift(); // O(n)
|
|
1167
|
+
}
|
|
1168
|
+
```
|
|
1169
|
+
|
|
1170
|
+
â
After:
|
|
1171
|
+
|
|
1172
|
+
```javascript
|
|
1173
|
+
import { Deque } from 'data-structure-typed';
|
|
1174
|
+
|
|
1175
|
+
const deque = new Deque([1, 2, 3, 4, 5]);
|
|
1176
|
+
for (let i = 0; i < 100000; i++) {
|
|
1177
|
+
deque.shift(); // O(1)
|
|
1178
|
+
}
|
|
1179
|
+
```
|
|
215
1180
|
|
|
216
|
-
###
|
|
1181
|
+
### Pattern 2: Replacing unsorted Map with RedBlackTree
|
|
217
1182
|
|
|
218
|
-
|
|
1183
|
+
â Before:
|
|
219
1184
|
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
1185
|
+
```javascript
|
|
1186
|
+
const userMap = new Map([
|
|
1187
|
+
[5, { id: 5, name: 'Alice' }],
|
|
1188
|
+
[2, { id: 2, name: 'Bob' }],
|
|
1189
|
+
]);
|
|
1190
|
+
|
|
1191
|
+
for (const [id, user] of userMap) {
|
|
1192
|
+
console.log(id); // 5, 2 (insertion order)
|
|
1193
|
+
}
|
|
1194
|
+
```
|
|
1195
|
+
|
|
1196
|
+
â
After:
|
|
1197
|
+
|
|
1198
|
+
```javascript
|
|
1199
|
+
import { RedBlackTree } from 'data-structure-typed';
|
|
1200
|
+
|
|
1201
|
+
const userTree = new RedBlackTree([
|
|
1202
|
+
[5, { id: 5, name: 'Alice' }],
|
|
1203
|
+
[2, { id: 2, name: 'Bob' }],
|
|
1204
|
+
]);
|
|
1205
|
+
|
|
1206
|
+
for (const [id, user] of userTree) {
|
|
1207
|
+
console.log(id); // 2, 5 (sorted order)
|
|
1208
|
+
}
|
|
1209
|
+
```
|
|
1210
|
+
|
|
1211
|
+
### Pattern 3: Replacing Array.sort with PriorityQueue
|
|
1212
|
+
|
|
1213
|
+
â Before:
|
|
1214
|
+
|
|
1215
|
+
```javascript
|
|
1216
|
+
const tasks = [];
|
|
1217
|
+
for (const task of incomingTasks) {
|
|
1218
|
+
tasks.push(task);
|
|
1219
|
+
}
|
|
1220
|
+
tasks.sort((a, b) => b.priority - a.priority); // O(n log n)
|
|
1221
|
+
```
|
|
1222
|
+
|
|
1223
|
+
â
After:
|
|
1224
|
+
|
|
1225
|
+
```javascript
|
|
1226
|
+
import { MaxPriorityQueue } from 'data-structure-typed';
|
|
1227
|
+
|
|
1228
|
+
const pq = new MaxPriorityQueue();
|
|
1229
|
+
for (const task of incomingTasks) {
|
|
1230
|
+
pq.add(task); // O(log n)
|
|
1231
|
+
}
|
|
1232
|
+
```
|
|
1233
|
+
|
|
1234
|
+
---
|
|
1235
|
+
|
|
1236
|
+
## đ¯ Decision Guide: Choose the Right Data Structure
|
|
1237
|
+
|
|
1238
|
+
```
|
|
1239
|
+
Need frequent head/tail operations?
|
|
1240
|
+
â
|
|
1241
|
+
Yes â Deque (O(1) shift/unshift)
|
|
1242
|
+
No â Continue
|
|
1243
|
+
|
|
1244
|
+
Need sorted + fast queries?
|
|
1245
|
+
â
|
|
1246
|
+
Yes â RedBlackTree (O(log n) search)
|
|
1247
|
+
No â Continue
|
|
1248
|
+
|
|
1249
|
+
Need priority handling?
|
|
1250
|
+
â
|
|
1251
|
+
Yes â PriorityQueue (O(log n) add)
|
|
1252
|
+
No â Continue
|
|
1253
|
+
|
|
1254
|
+
Need prefix matching?
|
|
1255
|
+
â
|
|
1256
|
+
Yes â Trie (O(m + k) search)
|
|
1257
|
+
No â Continue
|
|
1258
|
+
|
|
1259
|
+
Need graph algorithms?
|
|
1260
|
+
â
|
|
1261
|
+
Yes â DirectedGraph / UndirectedGraph
|
|
1262
|
+
No â Use Array
|
|
1263
|
+
```
|
|
1264
|
+
|
|
1265
|
+
---
|
|
1266
|
+
|
|
1267
|
+
## đ Data Structures Available
|
|
262
1268
|
|
|
263
1269
|
<table style="display: table; width:100%; table-layout: fixed;">
|
|
264
1270
|
<thead>
|
|
@@ -274,263 +1280,349 @@ We provide data structures that are not available in JS/TS
|
|
|
274
1280
|
<tbody>
|
|
275
1281
|
<tr>
|
|
276
1282
|
<td>Binary Tree</td>
|
|
277
|
-
<td
|
|
278
|
-
<td
|
|
279
|
-
<td><a href="https://data-structure-typed-docs.vercel.app/classes/BinaryTree.html"
|
|
280
|
-
<td><a href="https://www.npmjs.com/package/binary-tree-typed"
|
|
1283
|
+
<td>â
</td>
|
|
1284
|
+
<td>â
</td>
|
|
1285
|
+
<td><a href="https://data-structure-typed-docs.vercel.app/classes/BinaryTree.html">Docs</a></td>
|
|
1286
|
+
<td><a href="https://www.npmjs.com/package/binary-tree-typed">NPM</a></td>
|
|
281
1287
|
<td><img alt="NPM Downloads" src="https://img.shields.io/npm/dm/binary-tree-typed"></td>
|
|
282
1288
|
</tr>
|
|
283
1289
|
<tr>
|
|
284
1290
|
<td>Binary Search Tree (BST)</td>
|
|
285
|
-
<td
|
|
286
|
-
<td
|
|
287
|
-
<td><a href="https://data-structure-typed-docs.vercel.app/classes/BST.html"
|
|
288
|
-
<td><a href="https://www.npmjs.com/package/bst-typed"
|
|
1291
|
+
<td>â
</td>
|
|
1292
|
+
<td>â
</td>
|
|
1293
|
+
<td><a href="https://data-structure-typed-docs.vercel.app/classes/BST.html">Docs</a></td>
|
|
1294
|
+
<td><a href="https://www.npmjs.com/package/bst-typed">NPM</a></td>
|
|
289
1295
|
<td><img alt="NPM Downloads" src="https://img.shields.io/npm/dm/bst-typed"></td>
|
|
290
1296
|
</tr>
|
|
291
1297
|
<tr>
|
|
292
1298
|
<td>AVL Tree</td>
|
|
293
|
-
<td
|
|
294
|
-
<td
|
|
295
|
-
<td><a href="https://data-structure-typed-docs.vercel.app/classes/AVLTree.html"
|
|
296
|
-
<td><a href="https://www.npmjs.com/package/avl-tree-typed"
|
|
1299
|
+
<td>â
</td>
|
|
1300
|
+
<td>â
</td>
|
|
1301
|
+
<td><a href="https://data-structure-typed-docs.vercel.app/classes/AVLTree.html">Docs</a></td>
|
|
1302
|
+
<td><a href="https://www.npmjs.com/package/avl-tree-typed">NPM</a></td>
|
|
297
1303
|
<td><img alt="NPM Downloads" src="https://img.shields.io/npm/dm/avl-tree-typed"></td>
|
|
298
1304
|
</tr>
|
|
299
1305
|
<tr>
|
|
300
1306
|
<td>Red Black Tree</td>
|
|
301
|
-
<td
|
|
302
|
-
<td
|
|
303
|
-
<td><a href="https://data-structure-typed-docs.vercel.app/classes/RedBlackTree.html"
|
|
304
|
-
<td><a href="https://www.npmjs.com/package/red-black-tree-typed"
|
|
1307
|
+
<td>â
</td>
|
|
1308
|
+
<td>â
</td>
|
|
1309
|
+
<td><a href="https://data-structure-typed-docs.vercel.app/classes/RedBlackTree.html">Docs</a></td>
|
|
1310
|
+
<td><a href="https://www.npmjs.com/package/red-black-tree-typed">NPM</a></td>
|
|
305
1311
|
<td><img alt="NPM Downloads" src="https://img.shields.io/npm/dm/red-black-tree-typed"></td>
|
|
306
1312
|
</tr>
|
|
307
1313
|
<tr>
|
|
308
1314
|
<td>Tree Multimap</td>
|
|
309
|
-
<td
|
|
310
|
-
<td
|
|
311
|
-
<td><a href="https://data-structure-typed-docs.vercel.app/classes/TreeMultiMap.html"
|
|
312
|
-
<td><a href="https://www.npmjs.com/package/tree-multimap-typed"
|
|
1315
|
+
<td>â
</td>
|
|
1316
|
+
<td>â
</td>
|
|
1317
|
+
<td><a href="https://data-structure-typed-docs.vercel.app/classes/TreeMultiMap.html">Docs</a></td>
|
|
1318
|
+
<td><a href="https://www.npmjs.com/package/tree-multimap-typed">NPM</a></td>
|
|
313
1319
|
<td><img alt="NPM Downloads" src="https://img.shields.io/npm/dm/tree-multimap-typed"></td>
|
|
314
1320
|
</tr>
|
|
315
1321
|
<tr>
|
|
316
1322
|
<td>Heap</td>
|
|
317
|
-
<td
|
|
318
|
-
<td
|
|
319
|
-
<td><a href="https://data-structure-typed-docs.vercel.app/classes/Heap.html"
|
|
320
|
-
<td><a href="https://www.npmjs.com/package/heap-typed"
|
|
1323
|
+
<td>â
</td>
|
|
1324
|
+
<td>â
</td>
|
|
1325
|
+
<td><a href="https://data-structure-typed-docs.vercel.app/classes/Heap.html">Docs</a></td>
|
|
1326
|
+
<td><a href="https://www.npmjs.com/package/heap-typed">NPM</a></td>
|
|
321
1327
|
<td><img alt="NPM Downloads" src="https://img.shields.io/npm/dm/heap-typed"></td>
|
|
322
1328
|
</tr>
|
|
323
1329
|
<tr>
|
|
324
1330
|
<td>Priority Queue</td>
|
|
325
|
-
<td
|
|
326
|
-
<td
|
|
327
|
-
<td><a href="https://data-structure-typed-docs.vercel.app/classes/PriorityQueue.html"
|
|
328
|
-
<td><a href="https://www.npmjs.com/package/priority-queue-typed"
|
|
1331
|
+
<td>â
</td>
|
|
1332
|
+
<td>â
</td>
|
|
1333
|
+
<td><a href="https://data-structure-typed-docs.vercel.app/classes/PriorityQueue.html">Docs</a></td>
|
|
1334
|
+
<td><a href="https://www.npmjs.com/package/priority-queue-typed">NPM</a></td>
|
|
329
1335
|
<td><img alt="NPM Downloads" src="https://img.shields.io/npm/dm/priority-queue-typed"></td>
|
|
330
1336
|
</tr>
|
|
331
1337
|
<tr>
|
|
332
1338
|
<td>Max Priority Queue</td>
|
|
333
|
-
<td
|
|
334
|
-
<td
|
|
335
|
-
<td><a href="https://data-structure-typed-docs.vercel.app/classes/MaxPriorityQueue.html"
|
|
336
|
-
<td><a href="https://www.npmjs.com/package/max-priority-queue-typed"
|
|
1339
|
+
<td>â
</td>
|
|
1340
|
+
<td>â
</td>
|
|
1341
|
+
<td><a href="https://data-structure-typed-docs.vercel.app/classes/MaxPriorityQueue.html">Docs</a></td>
|
|
1342
|
+
<td><a href="https://www.npmjs.com/package/max-priority-queue-typed">NPM</a></td>
|
|
337
1343
|
<td><img alt="NPM Downloads" src="https://img.shields.io/npm/dm/max-priority-queue-typed"></td>
|
|
338
1344
|
</tr>
|
|
339
1345
|
<tr>
|
|
340
1346
|
<td>Min Priority Queue</td>
|
|
341
|
-
<td
|
|
342
|
-
<td
|
|
343
|
-
<td><a href="https://data-structure-typed-docs.vercel.app/classes/MinPriorityQueue.html"
|
|
344
|
-
<td><a href="https://www.npmjs.com/package/min-priority-queue-typed"
|
|
1347
|
+
<td>â
</td>
|
|
1348
|
+
<td>â
</td>
|
|
1349
|
+
<td><a href="https://data-structure-typed-docs.vercel.app/classes/MinPriorityQueue.html">Docs</a></td>
|
|
1350
|
+
<td><a href="https://www.npmjs.com/package/min-priority-queue-typed">NPM</a></td>
|
|
345
1351
|
<td><img alt="NPM Downloads" src="https://img.shields.io/npm/dm/min-priority-queue-typed"></td>
|
|
346
1352
|
</tr>
|
|
347
1353
|
<tr>
|
|
348
1354
|
<td>Trie</td>
|
|
349
|
-
<td
|
|
350
|
-
<td
|
|
351
|
-
<td><a href="https://data-structure-typed-docs.vercel.app/classes/Trie.html"
|
|
352
|
-
<td><a href="https://www.npmjs.com/package/trie-typed"
|
|
1355
|
+
<td>â
</td>
|
|
1356
|
+
<td>â
</td>
|
|
1357
|
+
<td><a href="https://data-structure-typed-docs.vercel.app/classes/Trie.html">Docs</a></td>
|
|
1358
|
+
<td><a href="https://www.npmjs.com/package/trie-typed">NPM</a></td>
|
|
353
1359
|
<td><img alt="NPM Downloads" src="https://img.shields.io/npm/dm/trie-typed"></td>
|
|
354
1360
|
</tr>
|
|
355
1361
|
<tr>
|
|
356
1362
|
<td>Graph</td>
|
|
357
|
-
<td
|
|
358
|
-
<td
|
|
359
|
-
<td><a href="https://data-structure-typed-docs.vercel.app/classes/AbstractGraph.html"
|
|
360
|
-
<td><a href="https://www.npmjs.com/package/graph-typed"
|
|
1363
|
+
<td>â
</td>
|
|
1364
|
+
<td>â
</td>
|
|
1365
|
+
<td><a href="https://data-structure-typed-docs.vercel.app/classes/AbstractGraph.html">Docs</a></td>
|
|
1366
|
+
<td><a href="https://www.npmjs.com/package/graph-typed">NPM</a></td>
|
|
361
1367
|
<td><img alt="NPM Downloads" src="https://img.shields.io/npm/dm/graph-typed"></td>
|
|
362
1368
|
</tr>
|
|
363
1369
|
<tr>
|
|
364
1370
|
<td>Directed Graph</td>
|
|
365
|
-
<td
|
|
366
|
-
<td
|
|
367
|
-
<td><a href="https://data-structure-typed-docs.vercel.app/classes/DirectedGraph.html"
|
|
368
|
-
<td><a href="https://www.npmjs.com/package/directed-graph-typed"
|
|
1371
|
+
<td>â
</td>
|
|
1372
|
+
<td>â
</td>
|
|
1373
|
+
<td><a href="https://data-structure-typed-docs.vercel.app/classes/DirectedGraph.html">Docs</a></td>
|
|
1374
|
+
<td><a href="https://www.npmjs.com/package/directed-graph-typed">NPM</a></td>
|
|
369
1375
|
<td><img alt="NPM Downloads" src="https://img.shields.io/npm/dm/directed-graph-typed"></td>
|
|
370
1376
|
</tr>
|
|
371
1377
|
<tr>
|
|
372
1378
|
<td>Undirected Graph</td>
|
|
373
|
-
<td
|
|
374
|
-
<td
|
|
375
|
-
<td><a href="https://data-structure-typed-docs.vercel.app/classes/UndirectedGraph.html"
|
|
376
|
-
<td><a href="https://www.npmjs.com/package/undirected-graph-typed"
|
|
1379
|
+
<td>â
</td>
|
|
1380
|
+
<td>â
</td>
|
|
1381
|
+
<td><a href="https://data-structure-typed-docs.vercel.app/classes/UndirectedGraph.html">Docs</a></td>
|
|
1382
|
+
<td><a href="https://www.npmjs.com/package/undirected-graph-typed">NPM</a></td>
|
|
377
1383
|
<td><img alt="NPM Downloads" src="https://img.shields.io/npm/dm/undirected-graph-typed"></td>
|
|
378
1384
|
</tr>
|
|
379
1385
|
<tr>
|
|
380
1386
|
<td>Queue</td>
|
|
381
|
-
<td
|
|
382
|
-
<td
|
|
383
|
-
<td><a href="https://data-structure-typed-docs.vercel.app/classes/Queue.html"
|
|
384
|
-
<td><a href="https://www.npmjs.com/package/queue-typed"
|
|
1387
|
+
<td>â
</td>
|
|
1388
|
+
<td>â
</td>
|
|
1389
|
+
<td><a href="https://data-structure-typed-docs.vercel.app/classes/Queue.html">Docs</a></td>
|
|
1390
|
+
<td><a href="https://www.npmjs.com/package/queue-typed">NPM</a></td>
|
|
385
1391
|
<td><img alt="NPM Downloads" src="https://img.shields.io/npm/dm/queue-typed"></td>
|
|
386
1392
|
</tr>
|
|
387
1393
|
<tr>
|
|
388
1394
|
<td>Deque</td>
|
|
389
|
-
<td
|
|
390
|
-
<td
|
|
391
|
-
<td><a href="https://data-structure-typed-docs.vercel.app/classes/Deque.html"
|
|
392
|
-
<td><a href="https://www.npmjs.com/package/deque-typed"
|
|
1395
|
+
<td>â
</td>
|
|
1396
|
+
<td>â
</td>
|
|
1397
|
+
<td><a href="https://data-structure-typed-docs.vercel.app/classes/Deque.html">Docs</a></td>
|
|
1398
|
+
<td><a href="https://www.npmjs.com/package/deque-typed">NPM</a></td>
|
|
393
1399
|
<td><img alt="NPM Downloads" src="https://img.shields.io/npm/dm/deque-typed"></td>
|
|
394
1400
|
</tr>
|
|
395
1401
|
<tr>
|
|
396
1402
|
<td>Hash Map</td>
|
|
397
|
-
<td
|
|
398
|
-
<td
|
|
399
|
-
<td><a href="https://data-structure-typed-docs.vercel.app/classes/HashMap.html"
|
|
400
|
-
<td><a href="https://www.npmjs.com/package/hashmap-typed"
|
|
1403
|
+
<td>â
</td>
|
|
1404
|
+
<td>â
</td>
|
|
1405
|
+
<td><a href="https://data-structure-typed-docs.vercel.app/classes/HashMap.html">Docs</a></td>
|
|
1406
|
+
<td><a href="https://www.npmjs.com/package/hashmap-typed">NPM</a></td>
|
|
401
1407
|
<td></td>
|
|
402
1408
|
</tr>
|
|
403
1409
|
<tr>
|
|
404
1410
|
<td>Linked List</td>
|
|
405
|
-
<td
|
|
406
|
-
<td
|
|
407
|
-
<td><a href="https://data-structure-typed-docs.vercel.app/classes/SinglyLinkedList.html"
|
|
408
|
-
<td><a href="https://www.npmjs.com/package/linked-list-typed"
|
|
1411
|
+
<td>â
</td>
|
|
1412
|
+
<td>â
</td>
|
|
1413
|
+
<td><a href="https://data-structure-typed-docs.vercel.app/classes/SinglyLinkedList.html">Docs</a></td>
|
|
1414
|
+
<td><a href="https://www.npmjs.com/package/linked-list-typed">NPM</a></td>
|
|
409
1415
|
<td><img alt="NPM Downloads" src="https://img.shields.io/npm/dm/linked-list-typed"></td>
|
|
410
1416
|
</tr>
|
|
411
1417
|
<tr>
|
|
412
1418
|
<td>Singly Linked List</td>
|
|
413
|
-
<td
|
|
414
|
-
<td
|
|
415
|
-
<td><a href="https://data-structure-typed-docs.vercel.app/classes/SinglyLinkedList.html"
|
|
416
|
-
<td><a href="https://www.npmjs.com/package/singly-linked-list-typed"
|
|
1419
|
+
<td>â
</td>
|
|
1420
|
+
<td>â
</td>
|
|
1421
|
+
<td><a href="https://data-structure-typed-docs.vercel.app/classes/SinglyLinkedList.html">Docs</a></td>
|
|
1422
|
+
<td><a href="https://www.npmjs.com/package/singly-linked-list-typed">NPM</a></td>
|
|
417
1423
|
<td><img alt="NPM Downloads" src="https://img.shields.io/npm/dm/singly-linked-list-typed"></td>
|
|
418
1424
|
</tr>
|
|
419
1425
|
<tr>
|
|
420
1426
|
<td>Doubly Linked List</td>
|
|
421
|
-
<td
|
|
422
|
-
<td
|
|
423
|
-
<td><a href="https://data-structure-typed-docs.vercel.app/classes/DoublyLinkedList.html"
|
|
424
|
-
<td><a href="https://www.npmjs.com/package/doubly-linked-list-typed"
|
|
1427
|
+
<td>â
</td>
|
|
1428
|
+
<td>â
</td>
|
|
1429
|
+
<td><a href="https://data-structure-typed-docs.vercel.app/classes/DoublyLinkedList.html">Docs</a></td>
|
|
1430
|
+
<td><a href="https://www.npmjs.com/package/doubly-linked-list-typed">NPM</a></td>
|
|
425
1431
|
<td><img alt="NPM Downloads" src="https://img.shields.io/npm/dm/doubly-linked-list-typed"></td>
|
|
426
1432
|
</tr>
|
|
427
1433
|
<tr>
|
|
428
1434
|
<td>Stack</td>
|
|
429
|
-
<td
|
|
430
|
-
<td
|
|
431
|
-
<td><a href="https://data-structure-typed-docs.vercel.app/classes/Stack.html"
|
|
432
|
-
<td><a href="https://www.npmjs.com/package/stack-typed"
|
|
1435
|
+
<td>â
</td>
|
|
1436
|
+
<td>â
</td>
|
|
1437
|
+
<td><a href="https://data-structure-typed-docs.vercel.app/classes/Stack.html">Docs</a></td>
|
|
1438
|
+
<td><a href="https://www.npmjs.com/package/stack-typed">NPM</a></td>
|
|
433
1439
|
<td><img alt="NPM Downloads" src="https://img.shields.io/npm/dm/stack-typed"></td>
|
|
434
1440
|
</tr>
|
|
435
1441
|
<tr>
|
|
436
1442
|
<td>Segment Tree</td>
|
|
437
|
-
<td
|
|
1443
|
+
<td>â
</td>
|
|
438
1444
|
<td></td>
|
|
439
|
-
<td><a href="https://data-structure-typed-docs.vercel.app/classes/SegmentTree.html"
|
|
440
|
-
<td><a href="https://www.npmjs.com/package/segment-tree-typed"
|
|
1445
|
+
<td><a href="https://data-structure-typed-docs.vercel.app/classes/SegmentTree.html">Docs</a></td>
|
|
1446
|
+
<td><a href="https://www.npmjs.com/package/segment-tree-typed">NPM</a></td>
|
|
441
1447
|
<td></td>
|
|
442
1448
|
</tr>
|
|
443
1449
|
<tr>
|
|
444
1450
|
<td>Binary Indexed Tree</td>
|
|
445
|
-
<td
|
|
1451
|
+
<td>â
</td>
|
|
446
1452
|
<td></td>
|
|
447
|
-
<td><a href="https://data-structure-typed-docs.vercel.app/classes/BinaryIndexedTree.html"
|
|
448
|
-
<td><a href="https://www.npmjs.com/package/binary-indexed-tree-typed"
|
|
1453
|
+
<td><a href="https://data-structure-typed-docs.vercel.app/classes/BinaryIndexedTree.html">Docs</a></td>
|
|
1454
|
+
<td><a href="https://www.npmjs.com/package/binary-indexed-tree-typed">NPM</a></td>
|
|
449
1455
|
<td></td>
|
|
450
1456
|
</tr>
|
|
451
1457
|
</tbody>
|
|
452
1458
|
</table>
|
|
453
1459
|
|
|
454
|
-
|
|
1460
|
+
---
|
|
455
1461
|
|
|
456
|
-
|
|
1462
|
+
## đ¨ Vivid Examples: Visual Demonstrations
|
|
1463
|
+
|
|
1464
|
+
[Try it out](https://vivid-algorithm.vercel.app/), or you can run your own code using our [visual tool](https://github.com/zrwusa/vivid-algorithm)
|
|
457
1465
|
|
|
458
|
-
|
|
459
|
-
our [visual tool](https://github.com/zrwusa/vivid-algorithm)
|
|
1466
|
+
### AVL Tree
|
|
460
1467
|
|
|
461
1468
|

|
|
462
1469
|
|
|
463
1470
|
### Tree Multi Map
|
|
464
1471
|
|
|
465
|
-
[Try it out](https://vivid-algorithm.vercel.app/)
|
|
466
|
-
|
|
467
1472
|

|
|
468
1473
|
|
|
469
1474
|
### Directed Graph
|
|
470
1475
|
|
|
471
|
-
[Try it out](https://vivid-algorithm.vercel.app/algorithm/graph/)
|
|
472
|
-
|
|
473
1476
|

|
|
474
1477
|
|
|
475
1478
|
### Map Graph
|
|
476
1479
|
|
|
477
|
-
[Try it out](https://vivid-algorithm.vercel.app/algorithm/graph/)
|
|
478
|
-
|
|
479
1480
|

|
|
480
1481
|
|
|
481
|
-
|
|
1482
|
+
---
|
|
482
1483
|
|
|
483
|
-
|
|
1484
|
+
## đ Integration Examples
|
|
484
1485
|
|
|
485
|
-
|
|
1486
|
+
### React: State Management with Sorted Data
|
|
486
1487
|
|
|
487
|
-
```
|
|
1488
|
+
```tsx
|
|
1489
|
+
import { useMemo, useState } from 'react';
|
|
488
1490
|
import { RedBlackTree } from 'data-structure-typed';
|
|
489
1491
|
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
1492
|
+
type TodoItem = { id: number; title: string };
|
|
1493
|
+
|
|
1494
|
+
export default function TodoList() {
|
|
1495
|
+
const [todoTree, setTodoTree] = useState(
|
|
1496
|
+
new RedBlackTree<number, TodoItem>([
|
|
1497
|
+
[100, { id: 100, title: 'Title 100' }],
|
|
1498
|
+
[1, { id: 1, title: 'Title 1' }],
|
|
1499
|
+
])
|
|
1500
|
+
);
|
|
1501
|
+
|
|
1502
|
+
const todos = useMemo(() => [...todoTree.values()], [todoTree]);
|
|
1503
|
+
|
|
1504
|
+
const addTodo = () => {
|
|
1505
|
+
setTodoTree((prev) => {
|
|
1506
|
+
const next = prev.clone();
|
|
1507
|
+
let id = Math.floor(Math.random() * 100);
|
|
1508
|
+
while (next.has(id)) {
|
|
1509
|
+
id = Math.floor(Math.random() * 100);
|
|
1510
|
+
}
|
|
1511
|
+
next.add(id, { id, title: `Title ${id}` });
|
|
1512
|
+
return next;
|
|
1513
|
+
});
|
|
1514
|
+
};
|
|
1515
|
+
|
|
1516
|
+
const deleteTodo = (id: number) => {
|
|
1517
|
+
setTodoTree((prev) => {
|
|
1518
|
+
const next = prev.clone();
|
|
1519
|
+
next.delete(id);
|
|
1520
|
+
return next;
|
|
1521
|
+
});
|
|
1522
|
+
};
|
|
1523
|
+
|
|
1524
|
+
return (
|
|
1525
|
+
<div>
|
|
1526
|
+
<h2>Todo List (sorted by id)</h2>
|
|
1527
|
+
{/* Component implementation */}
|
|
1528
|
+
</div>
|
|
1529
|
+
);
|
|
1530
|
+
}
|
|
505
1531
|
```
|
|
506
1532
|
|
|
507
|
-
|
|
1533
|
+
### Express.js: In-Memory Cache with LRU
|
|
1534
|
+
|
|
1535
|
+
```typescript
|
|
1536
|
+
import express from 'express';
|
|
1537
|
+
import { DoublyLinkedList } from 'data-structure-typed';
|
|
1538
|
+
|
|
1539
|
+
interface CacheEntry {
|
|
1540
|
+
key: string;
|
|
1541
|
+
value: any;
|
|
1542
|
+
}
|
|
1543
|
+
|
|
1544
|
+
class ApiCache {
|
|
1545
|
+
private cache = new DoublyLinkedList<CacheEntry>();
|
|
1546
|
+
private keyMap = new Map<string, any>();
|
|
1547
|
+
private maxSize = 1000;
|
|
1548
|
+
|
|
1549
|
+
set(key: string, value: any): void {
|
|
1550
|
+
const entry: CacheEntry = { key, value };
|
|
1551
|
+
this.cache.push(entry);
|
|
1552
|
+
this.keyMap.set(key, value);
|
|
1553
|
+
|
|
1554
|
+
if (this.cache.size > this.maxSize) {
|
|
1555
|
+
const oldest = this.cache.shift();
|
|
1556
|
+
if (oldest) {
|
|
1557
|
+
this.keyMap.delete(oldest.key);
|
|
1558
|
+
}
|
|
1559
|
+
}
|
|
1560
|
+
}
|
|
1561
|
+
|
|
1562
|
+
get(key: string): any {
|
|
1563
|
+
return this.keyMap.get(key);
|
|
1564
|
+
}
|
|
1565
|
+
}
|
|
1566
|
+
|
|
1567
|
+
const app = express();
|
|
1568
|
+
const cache = new ApiCache();
|
|
1569
|
+
|
|
1570
|
+
app.get('/api/user/:id', (req, res) => {
|
|
1571
|
+
const cacheKey = `user:${req.params.id}`;
|
|
1572
|
+
let userData = cache.get(cacheKey);
|
|
1573
|
+
if (!userData) {
|
|
1574
|
+
userData = { id: req.params.id, name: 'User' };
|
|
1575
|
+
cache.set(cacheKey, userData);
|
|
1576
|
+
}
|
|
1577
|
+
res.json(userData);
|
|
1578
|
+
});
|
|
1579
|
+
```
|
|
508
1580
|
|
|
509
|
-
|
|
1581
|
+
### Nest.js: Service with Tree-Based Ranking
|
|
1582
|
+
|
|
1583
|
+
```typescript
|
|
1584
|
+
import { Injectable } from '@nestjs/common';
|
|
510
1585
|
import { RedBlackTree } from 'data-structure-typed';
|
|
511
1586
|
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
1587
|
+
interface RankEntry {
|
|
1588
|
+
userId: string;
|
|
1589
|
+
score: number;
|
|
1590
|
+
}
|
|
1591
|
+
|
|
1592
|
+
@Injectable()
|
|
1593
|
+
export class RankingService {
|
|
1594
|
+
private rankingTree = new RedBlackTree<number, RankEntry>();
|
|
1595
|
+
|
|
1596
|
+
updateScore(userId: string, newScore: number): void {
|
|
1597
|
+
const existing = [...this.rankingTree.values()].find(
|
|
1598
|
+
(e) => e?.userId === userId
|
|
1599
|
+
);
|
|
1600
|
+
|
|
1601
|
+
if (existing) {
|
|
1602
|
+
this.rankingTree.delete(existing.score);
|
|
1603
|
+
}
|
|
1604
|
+
|
|
1605
|
+
this.rankingTree.add(newScore, { userId, score: newScore });
|
|
1606
|
+
}
|
|
1607
|
+
|
|
1608
|
+
getRanking(topN: number = 100): RankEntry[] | undefined {
|
|
1609
|
+
return [...this.rankingTree.values()].reverse().slice(0, topN);
|
|
1610
|
+
}
|
|
1611
|
+
|
|
1612
|
+
getUserRank(userId: string): number | null {
|
|
1613
|
+
const allEntries = [...this.rankingTree.values()].reverse();
|
|
1614
|
+
const index = allEntries.findIndex((e) => e?.userId === userId);
|
|
1615
|
+
return index >= 0 ? index + 1 : null;
|
|
1616
|
+
}
|
|
1617
|
+
}
|
|
527
1618
|
```
|
|
528
1619
|
|
|
529
|
-
|
|
1620
|
+
---
|
|
1621
|
+
|
|
1622
|
+
## Free Conversion Between Data Structures
|
|
530
1623
|
|
|
531
1624
|
```js
|
|
532
1625
|
const orgArr = [6, 1, 2, 7, 5, 3, 4, 9, 8];
|
|
533
|
-
const orgStrArr = ["trie", "trial", "trick", "trip", "tree", "trend", "triangle", "track", "trace", "transmit"];
|
|
534
1626
|
const entries = [[6, "6"], [1, "1"], [2, "2"], [7, "7"], [5, "5"], [3, "3"], [4, "4"], [9, "9"], [8, "8"]];
|
|
535
1627
|
|
|
536
1628
|
const queue = new Queue(orgArr);
|
|
@@ -581,7 +1673,6 @@ bst.print();
|
|
|
581
1673
|
// \ \
|
|
582
1674
|
// 4 9
|
|
583
1675
|
|
|
584
|
-
|
|
585
1676
|
const rbTree = new RedBlackTree(entries);
|
|
586
1677
|
rbTree.print();
|
|
587
1678
|
// ___4___
|
|
@@ -592,7 +1683,6 @@ rbTree.print();
|
|
|
592
1683
|
// / \
|
|
593
1684
|
// 7 9
|
|
594
1685
|
|
|
595
|
-
|
|
596
1686
|
const avl = new AVLTree(entries);
|
|
597
1687
|
avl.print();
|
|
598
1688
|
// ___4___
|
|
@@ -653,611 +1743,147 @@ rbTree1.print();
|
|
|
653
1743
|
// 1 _4 6 _9
|
|
654
1744
|
// / /
|
|
655
1745
|
// 3 8
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
const trie2 = new Trie(orgStrArr);
|
|
659
|
-
trie2.print();
|
|
660
|
-
// ['trie', 'trial', 'triangle', 'trick', 'trip', 'tree', 'trend', 'track', 'trace', 'transmit']
|
|
661
|
-
const heap2 = new Heap(trie2, { comparator: (a, b) => Number(a) - Number(b) });
|
|
662
|
-
heap2.print();
|
|
663
|
-
// ['transmit', 'trace', 'tree', 'trend', 'track', 'trial', 'trip', 'trie', 'trick', 'triangle']
|
|
664
|
-
const dq2 = new Deque(heap2);
|
|
665
|
-
dq2.print();
|
|
666
|
-
// ['transmit', 'trace', 'tree', 'trend', 'track', 'trial', 'trip', 'trie', 'trick', 'triangle']
|
|
667
|
-
const entries2 = dq2.map((el, i) => [i, el]);
|
|
668
|
-
const avl2 = new AVLTree(entries2);
|
|
669
|
-
avl2.print();
|
|
670
|
-
// ___3_______
|
|
671
|
-
// / \
|
|
672
|
-
// _1_ ___7_
|
|
673
|
-
// / \ / \
|
|
674
|
-
// 0 2 _5_ 8_
|
|
675
|
-
// / \ \
|
|
676
|
-
// 4 6 9
|
|
677
|
-
```
|
|
678
|
-
|
|
679
|
-
### Binary Search Tree (BST) snippet
|
|
680
|
-
|
|
681
|
-
```ts
|
|
682
|
-
import { BST, BSTNode } from 'data-structure-typed';
|
|
683
|
-
|
|
684
|
-
const bst = new BST<number>();
|
|
685
|
-
bst.add(11);
|
|
686
|
-
bst.add(3);
|
|
687
|
-
bst.addMany([15, 1, 8, 13, 16, 2, 6, 9, 12, 14, 4, 7, 10, 5]);
|
|
688
|
-
bst.size === 16; // true
|
|
689
|
-
bst.has(6); // true
|
|
690
|
-
const node6 = bst.getNode(6); // BSTNode
|
|
691
|
-
bst.getHeight(6) === 2; // true
|
|
692
|
-
bst.getHeight() === 5; // true
|
|
693
|
-
bst.getDepth(6) === 3; // true
|
|
694
|
-
|
|
695
|
-
bst.getLeftMost()?.key === 1; // true
|
|
696
|
-
|
|
697
|
-
bst.delete(6);
|
|
698
|
-
bst.get(6); // undefined
|
|
699
|
-
bst.isAVLBalanced(); // true
|
|
700
|
-
bst.bfs()[0] === 11; // true
|
|
701
|
-
bst.print()
|
|
702
|
-
// ______________11_____
|
|
703
|
-
// / \
|
|
704
|
-
// ___3_______ _13_____
|
|
705
|
-
// / \ / \
|
|
706
|
-
// 1_ _____8____ 12 _15__
|
|
707
|
-
// \ / \ / \
|
|
708
|
-
// 2 4_ _10 14 16
|
|
709
|
-
// \ /
|
|
710
|
-
// 5_ 9
|
|
711
|
-
// \
|
|
712
|
-
// 7
|
|
713
|
-
|
|
714
|
-
const objBST = new BST<number, { height: number, age: number }>();
|
|
715
|
-
|
|
716
|
-
objBST.add(11, { "name": "Pablo", "size": 15 });
|
|
717
|
-
objBST.add(3, { "name": "Kirk", "size": 1 });
|
|
718
|
-
|
|
719
|
-
objBST.addMany([15, 1, 8, 13, 16, 2, 6, 9, 12, 14, 4, 7, 10, 5], [
|
|
720
|
-
{ "name": "Alice", "size": 15 },
|
|
721
|
-
{ "name": "Bob", "size": 1 },
|
|
722
|
-
{ "name": "Charlie", "size": 8 },
|
|
723
|
-
{ "name": "David", "size": 13 },
|
|
724
|
-
{ "name": "Emma", "size": 16 },
|
|
725
|
-
{ "name": "Frank", "size": 2 },
|
|
726
|
-
{ "name": "Grace", "size": 6 },
|
|
727
|
-
{ "name": "Hannah", "size": 9 },
|
|
728
|
-
{ "name": "Isaac", "size": 12 },
|
|
729
|
-
{ "name": "Jack", "size": 14 },
|
|
730
|
-
{ "name": "Katie", "size": 4 },
|
|
731
|
-
{ "name": "Liam", "size": 7 },
|
|
732
|
-
{ "name": "Mia", "size": 10 },
|
|
733
|
-
{ "name": "Noah", "size": 5 }
|
|
734
|
-
]
|
|
735
|
-
);
|
|
736
|
-
|
|
737
|
-
objBST.delete(11);
|
|
738
|
-
```
|
|
739
|
-
|
|
740
|
-
### AVLTree snippet
|
|
741
|
-
|
|
742
|
-
```ts
|
|
743
|
-
import { AVLTree } from 'data-structure-typed';
|
|
744
|
-
|
|
745
|
-
const avlTree = new AVLTree<number>();
|
|
746
|
-
avlTree.addMany([11, 3, 15, 1, 8, 13, 16, 2, 6, 9, 12, 14, 4, 7, 10, 5])
|
|
747
|
-
avlTree.isAVLBalanced(); // true
|
|
748
|
-
avlTree.delete(10);
|
|
749
|
-
avlTree.isAVLBalanced(); // true
|
|
750
1746
|
```
|
|
751
1747
|
|
|
752
|
-
|
|
1748
|
+
---
|
|
753
1749
|
|
|
754
|
-
|
|
755
|
-
import { DirectedGraph } from 'data-structure-typed';
|
|
1750
|
+
## Supported Module System
|
|
756
1751
|
|
|
757
|
-
|
|
1752
|
+
Now you can use it in Node.js and browser environments
|
|
758
1753
|
|
|
759
|
-
|
|
760
|
-
graph.addVertex('B');
|
|
1754
|
+
### Module Formats
|
|
761
1755
|
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
1756
|
+
- **CommonJS**: `require export.modules =`
|
|
1757
|
+
- **ESModule**: `import export`
|
|
1758
|
+
- **TypeScript**: `import export`
|
|
1759
|
+
- **UMD**: `var Deque = dataStructureTyped.Deque`
|
|
765
1760
|
|
|
766
|
-
|
|
767
|
-
graph.hasEdge('A', 'B'); // true
|
|
768
|
-
graph.hasEdge('B', 'A'); // false
|
|
1761
|
+
### CDN
|
|
769
1762
|
|
|
770
|
-
|
|
771
|
-
graph.hasEdge('A', 'B'); // false
|
|
1763
|
+
#### Development
|
|
772
1764
|
|
|
773
|
-
|
|
1765
|
+
##### ES Module
|
|
774
1766
|
|
|
775
|
-
|
|
776
|
-
|
|
1767
|
+
```html
|
|
1768
|
+
<script type="module">
|
|
1769
|
+
import { BST } from "https://cdn.jsdelivr.net/npm/data-structure-typed/dist/esm/index.mjs";
|
|
777
1770
|
|
|
778
|
-
const
|
|
1771
|
+
const bst = new BST([2, 1, 6, 7, 5, 3, 4, 8, 9]);
|
|
1772
|
+
bst.print();
|
|
1773
|
+
</script>
|
|
779
1774
|
```
|
|
780
1775
|
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
```ts
|
|
784
|
-
import { UndirectedGraph } from 'data-structure-typed';
|
|
785
|
-
|
|
786
|
-
const graph = new UndirectedGraph<string>();
|
|
787
|
-
graph.addVertex('A');
|
|
788
|
-
graph.addVertex('B');
|
|
789
|
-
graph.addVertex('C');
|
|
790
|
-
graph.addVertex('D');
|
|
791
|
-
graph.deleteVertex('C');
|
|
792
|
-
graph.addEdge('A', 'B');
|
|
793
|
-
graph.addEdge('B', 'D');
|
|
794
|
-
|
|
795
|
-
const dijkstraResult = graph.dijkstra('A');
|
|
796
|
-
Array.from(dijkstraResult?.seen ?? []).map(vertex => vertex.key) // ['A', 'B', 'D']
|
|
797
|
-
|
|
1776
|
+
##### UMD
|
|
798
1777
|
|
|
1778
|
+
```html
|
|
1779
|
+
<script src='https://cdn.jsdelivr.net/npm/data-structure-typed/dist/umd/data-structure-typed.js'></script>
|
|
799
1780
|
```
|
|
800
1781
|
|
|
1782
|
+
#### Production
|
|
801
1783
|
|
|
1784
|
+
```html
|
|
1785
|
+
<script src='https://cdn.jsdelivr.net/npm/data-structure-typed/dist/umd/data-structure-typed.min.js'></script>
|
|
802
1786
|
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
[
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
## Benchmark
|
|
812
|
-
|
|
813
|
-
MacBook Pro (15-inch, 2018)
|
|
814
|
-
|
|
815
|
-
Processor 2.2 GHz 6-Core Intel Core i7
|
|
816
|
-
|
|
817
|
-
Memory 16 GB 2400 MHz DDR4
|
|
818
|
-
|
|
819
|
-
Graphics Radeon Pro 555X 4 GB
|
|
820
|
-
|
|
821
|
-
Intel UHD Graphics 630 1536 MB
|
|
822
|
-
|
|
823
|
-
macOS Sequoia 15.7.2
|
|
824
|
-
|
|
825
|
-
## Performance & Runtime Compatibility
|
|
826
|
-
|
|
827
|
-
[//]: # (No deletion!!! Start of Replace Section)
|
|
828
|
-
|
|
829
|
-
<h2>red-black-tree</h2><table><thead><tr><th>test name</th><th>time taken (ms)</th><th>sample mean (secs)</th><th>sample deviation</th></tr></thead><tbody><tr><td>1,000,000 add</td><td>410.34</td><td>0.41</td><td>0.01</td></tr><tr><td>1,000,000 get</td><td>5.20</td><td>0.01</td><td>8.16e-5</td></tr><tr><td>1,000,000 iterator</td><td>154.25</td><td>0.15</td><td>0.02</td></tr><tr><td>CPT 1,000,000 add</td><td>656.43</td><td>0.66</td><td>0.00</td></tr><tr><td>CPT 1,000,000 add</td><td>684.17</td><td>0.68</td><td>0.01</td></tr></tbody></table><h2>queue</h2><table><thead><tr><th>test name</th><th>time taken (ms)</th><th>sample mean (secs)</th><th>sample deviation</th></tr></thead><tbody><tr><td>1,000,000 push</td><td>26.97</td><td>0.03</td><td>0.00</td></tr><tr><td>100,000 push & shift</td><td>2.87</td><td>0.00</td><td>2.71e-4</td></tr><tr><td>Native JS Array 100,000 push & shift</td><td>1120.94</td><td>1.12</td><td>0.20</td></tr></tbody></table><h2>deque</h2><table><thead><tr><th>test name</th><th>time taken (ms)</th><th>sample mean (secs)</th><th>sample deviation</th></tr></thead><tbody><tr><td>1,000,000 push</td><td>8.75</td><td>0.01</td><td>6.99e-4</td></tr><tr><td>1,000,000 push & pop</td><td>12.95</td><td>0.01</td><td>4.21e-4</td></tr><tr><td>1,000,000 push & shift</td><td>13.73</td><td>0.01</td><td>4.53e-4</td></tr><tr><td>100,000 push & shift</td><td>1.36</td><td>0.00</td><td>5.42e-5</td></tr><tr><td>Native JS Array 100,000 push & shift</td><td>1167.06</td><td>1.17</td><td>0.26</td></tr><tr><td>100,000 unshift & shift</td><td>1.31</td><td>0.00</td><td>4.73e-5</td></tr><tr><td>Native JS Array 100,000 unshift & shift</td><td>1911.47</td><td>1.91</td><td>0.02</td></tr></tbody></table><h2>heap</h2><table><thead><tr><th>test name</th><th>time taken (ms)</th><th>sample mean (secs)</th><th>sample deviation</th></tr></thead><tbody><tr><td>100,000 add</td><td>4.60</td><td>0.00</td><td>1.07e-4</td></tr><tr><td>100,000 add & poll</td><td>16.96</td><td>0.02</td><td>3.45e-4</td></tr></tbody></table><h2>avl-tree</h2><table><thead><tr><th>test name</th><th>time taken (ms)</th><th>sample mean (secs)</th><th>sample deviation</th></tr></thead><tbody><tr><td>100,000 add randomly</td><td>324.51</td><td>0.32</td><td>0.01</td></tr><tr><td>100,000 add</td><td>299.76</td><td>0.30</td><td>0.02</td></tr><tr><td>100,000 get</td><td>0.26</td><td>2.58e-4</td><td>3.65e-6</td></tr><tr><td>100,000 getNode</td><td>169.33</td><td>0.17</td><td>0.00</td></tr><tr><td>100,000 iterator</td><td>14.43</td><td>0.01</td><td>0.00</td></tr><tr><td>100,000 add & delete orderly</td><td>434.44</td><td>0.43</td><td>0.01</td></tr><tr><td>100,000 add & delete randomly</td><td>541.78</td><td>0.54</td><td>0.01</td></tr></tbody></table><h2>hash-map</h2><table><thead><tr><th>test name</th><th>time taken (ms)</th><th>sample mean (secs)</th><th>sample deviation</th></tr></thead><tbody><tr><td>1,000,000 set</td><td>43.23</td><td>0.04</td><td>0.01</td></tr><tr><td>Native JS Map 1,000,000 set</td><td>147.12</td><td>0.15</td><td>0.01</td></tr><tr><td>Native JS Set 1,000,000 add</td><td>116.18</td><td>0.12</td><td>0.01</td></tr><tr><td>1,000,000 set & get</td><td>46.39</td><td>0.05</td><td>0.01</td></tr><tr><td>Native JS Map 1,000,000 set & get</td><td>196.92</td><td>0.20</td><td>0.01</td></tr><tr><td>Native JS Set 1,000,000 add & has</td><td>163.92</td><td>0.16</td><td>0.01</td></tr><tr><td>1,000,000 ObjKey set & get</td><td>243.36</td><td>0.24</td><td>0.03</td></tr><tr><td>Native JS Map 1,000,000 ObjKey set & get</td><td>211.66</td><td>0.21</td><td>0.02</td></tr><tr><td>Native JS Set 1,000,000 ObjKey add & has</td><td>196.57</td><td>0.20</td><td>0.01</td></tr></tbody></table><h2>directed-graph</h2><table><thead><tr><th>test name</th><th>time taken (ms)</th><th>sample mean (secs)</th><th>sample deviation</th></tr></thead><tbody><tr><td>1,000 addVertex</td><td>0.05</td><td>4.60e-5</td><td>6.59e-7</td></tr><tr><td>1,000 addEdge</td><td>3.02</td><td>0.00</td><td>2.85e-4</td></tr><tr><td>1,000 getVertex</td><td>0.04</td><td>3.77e-5</td><td>4.66e-7</td></tr><tr><td>1,000 getEdge</td><td>41.48</td><td>0.04</td><td>0.01</td></tr><tr><td>tarjan</td><td>240.33</td><td>0.24</td><td>0.01</td></tr><tr><td>topologicalSort</td><td>195.62</td><td>0.20</td><td>0.01</td></tr></tbody></table><h2>trie</h2><table><thead><tr><th>test name</th><th>time taken (ms)</th><th>sample mean (secs)</th><th>sample deviation</th></tr></thead><tbody><tr><td>100,000 push</td><td>27.15</td><td>0.03</td><td>6.61e-4</td></tr><tr><td>100,000 getWords</td><td>41.18</td><td>0.04</td><td>0.00</td></tr></tbody></table><h2>stack</h2><table><thead><tr><th>test name</th><th>time taken (ms)</th><th>sample mean (secs)</th><th>sample deviation</th></tr></thead><tbody><tr><td>1,000,000 push</td><td>25.21</td><td>0.03</td><td>0.00</td></tr><tr><td>1,000,000 push & pop</td><td>29.12</td><td>0.03</td><td>0.00</td></tr></tbody></table>
|
|
830
|
-
|
|
831
|
-
[//]: # (No deletion!!! End of Replace Section)
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
## The corresponding relationships between data structures in different language standard libraries.
|
|
1787
|
+
<script>
|
|
1788
|
+
const { Heap } = dataStructureTyped;
|
|
1789
|
+
const { BinaryTree, Graph, Queue, Stack } = dataStructureTyped;
|
|
1790
|
+
|
|
1791
|
+
const heap = new Heap([1, 2, 3]);
|
|
1792
|
+
heap.print();
|
|
1793
|
+
</script>
|
|
1794
|
+
```
|
|
835
1795
|
|
|
836
|
-
|
|
837
|
-
<thead>
|
|
838
|
-
<tr>
|
|
839
|
-
<th>Data Structure Typed</th>
|
|
840
|
-
<th>C++ STL</th>
|
|
841
|
-
<th>java.util</th>
|
|
842
|
-
<th>Python collections</th>
|
|
843
|
-
</tr>
|
|
844
|
-
</thead>
|
|
845
|
-
<tbody>
|
|
846
|
-
<tr>
|
|
847
|
-
<td>Heap<E></td>
|
|
848
|
-
<td>-</td>
|
|
849
|
-
<td>-</td>
|
|
850
|
-
<td>heapq</td>
|
|
851
|
-
</tr>
|
|
852
|
-
<tr>
|
|
853
|
-
<td>PriorityQueue<E></td>
|
|
854
|
-
<td>priority_queue<T></td>
|
|
855
|
-
<td>PriorityQueue<E></td>
|
|
856
|
-
<td>-</td>
|
|
857
|
-
</tr>
|
|
858
|
-
<tr>
|
|
859
|
-
<td>Deque<E></td>
|
|
860
|
-
<td>deque<T></td>
|
|
861
|
-
<td>ArrayDeque<E></td>
|
|
862
|
-
<td>deque</td>
|
|
863
|
-
</tr>
|
|
864
|
-
<tr>
|
|
865
|
-
<td>Queue<E></td>
|
|
866
|
-
<td>queue<T></td>
|
|
867
|
-
<td>Queue<E></td>
|
|
868
|
-
<td>-</td>
|
|
869
|
-
</tr>
|
|
870
|
-
<tr>
|
|
871
|
-
<td>HashMap<K, V></td>
|
|
872
|
-
<td>unordered_map<K, V></td>
|
|
873
|
-
<td>HashMap<K, V></td>
|
|
874
|
-
<td>defaultdict</td>
|
|
875
|
-
</tr>
|
|
876
|
-
<tr>
|
|
877
|
-
<td>DoublyLinkedList<E></td>
|
|
878
|
-
<td>list<T></td>
|
|
879
|
-
<td>LinkedList<E></td>
|
|
880
|
-
<td>-</td>
|
|
881
|
-
</tr>
|
|
882
|
-
<tr>
|
|
883
|
-
<td>SinglyLinkedList<E></td>
|
|
884
|
-
<td>-</td>
|
|
885
|
-
<td>-</td>
|
|
886
|
-
<td>-</td>
|
|
887
|
-
</tr>
|
|
888
|
-
<tr>
|
|
889
|
-
<td>BinaryTree<K, V></td>
|
|
890
|
-
<td>-</td>
|
|
891
|
-
<td>-</td>
|
|
892
|
-
<td>-</td>
|
|
893
|
-
</tr>
|
|
894
|
-
<tr>
|
|
895
|
-
<td>BST<K, V></td>
|
|
896
|
-
<td>-</td>
|
|
897
|
-
<td>-</td>
|
|
898
|
-
<td>-</td>
|
|
899
|
-
</tr>
|
|
900
|
-
<tr>
|
|
901
|
-
<td>RedBlackTree<E></td>
|
|
902
|
-
<td>set<T></td>
|
|
903
|
-
<td>TreeSet<E></td>
|
|
904
|
-
<td>-</td>
|
|
905
|
-
</tr>
|
|
906
|
-
<tr>
|
|
907
|
-
<td>RedBlackTree<K, V></td>
|
|
908
|
-
<td>map<K, V></td>
|
|
909
|
-
<td>TreeMap<K, V></td>
|
|
910
|
-
<td>-</td>
|
|
911
|
-
</tr>
|
|
912
|
-
<tr>
|
|
913
|
-
<td>TreeMultiMap<K, V></td>
|
|
914
|
-
<td>multimap<K, V></td>
|
|
915
|
-
<td>-</td>
|
|
916
|
-
<td>-</td>
|
|
917
|
-
</tr>
|
|
918
|
-
<tr>
|
|
919
|
-
<td>TreeMultiMap<E></td>
|
|
920
|
-
<td>multiset<T></td>
|
|
921
|
-
<td>-</td>
|
|
922
|
-
<td>-</td>
|
|
923
|
-
</tr>
|
|
924
|
-
<tr>
|
|
925
|
-
<td>Trie</td>
|
|
926
|
-
<td>-</td>
|
|
927
|
-
<td>-</td>
|
|
928
|
-
<td>-</td>
|
|
929
|
-
</tr>
|
|
930
|
-
<tr>
|
|
931
|
-
<td>DirectedGraph<V, E></td>
|
|
932
|
-
<td>-</td>
|
|
933
|
-
<td>-</td>
|
|
934
|
-
<td>-</td>
|
|
935
|
-
</tr>
|
|
936
|
-
<tr>
|
|
937
|
-
<td>UndirectedGraph<V, E></td>
|
|
938
|
-
<td>-</td>
|
|
939
|
-
<td>-</td>
|
|
940
|
-
<td>-</td>
|
|
941
|
-
</tr>
|
|
942
|
-
<tr>
|
|
943
|
-
<td>PriorityQueue<E></td>
|
|
944
|
-
<td>priority_queue<T></td>
|
|
945
|
-
<td>PriorityQueue<E></td>
|
|
946
|
-
<td>-</td>
|
|
947
|
-
</tr>
|
|
948
|
-
<tr>
|
|
949
|
-
<td>Array<E></td>
|
|
950
|
-
<td>vector<T></td>
|
|
951
|
-
<td>ArrayList<E></td>
|
|
952
|
-
<td>list</td>
|
|
953
|
-
</tr>
|
|
954
|
-
<tr>
|
|
955
|
-
<td>Stack<E></td>
|
|
956
|
-
<td>stack<T></td>
|
|
957
|
-
<td>Stack<E></td>
|
|
958
|
-
<td>-</td>
|
|
959
|
-
</tr>
|
|
960
|
-
<tr>
|
|
961
|
-
<td>HashMap<E></td>
|
|
962
|
-
<td>unordered_set<T></td>
|
|
963
|
-
<td>HashSet<E></td>
|
|
964
|
-
<td>set</td>
|
|
965
|
-
</tr>
|
|
966
|
-
<tr>
|
|
967
|
-
<td>-</td>
|
|
968
|
-
<td>unordered_multiset</td>
|
|
969
|
-
<td>-</td>
|
|
970
|
-
<td>Counter</td>
|
|
971
|
-
</tr>
|
|
972
|
-
<tr>
|
|
973
|
-
<td>ES6 Map<K, V></td>
|
|
974
|
-
<td>-</td>
|
|
975
|
-
<td>LinkedHashMap<K, V></td>
|
|
976
|
-
<td>OrderedDict</td>
|
|
977
|
-
</tr>
|
|
978
|
-
<tr>
|
|
979
|
-
<td>-</td>
|
|
980
|
-
<td>unordered_multimap<K, V></td>
|
|
981
|
-
<td>-</td>
|
|
982
|
-
<td>-</td>
|
|
983
|
-
</tr>
|
|
984
|
-
<tr>
|
|
985
|
-
<td>-</td>
|
|
986
|
-
<td>bitset<N></td>
|
|
987
|
-
<td>-</td>
|
|
988
|
-
<td>-</td>
|
|
989
|
-
</tr>
|
|
990
|
-
</tbody>
|
|
991
|
-
</table>
|
|
1796
|
+
---
|
|
992
1797
|
|
|
993
|
-
##
|
|
1798
|
+
## Design Principles
|
|
994
1799
|
|
|
995
1800
|
<table style="display: table; width:100%; table-layout: fixed;">
|
|
996
|
-
<thead>
|
|
997
|
-
<tr>
|
|
998
|
-
<th>Algorithm</th>
|
|
999
|
-
<th>Function Description</th>
|
|
1000
|
-
<th>Iteration Type</th>
|
|
1001
|
-
</tr>
|
|
1002
|
-
</thead>
|
|
1003
|
-
<tbody>
|
|
1004
1801
|
<tr>
|
|
1005
|
-
<
|
|
1006
|
-
<
|
|
1007
|
-
and then the right subtree, using recursion.
|
|
1008
|
-
</td>
|
|
1009
|
-
<td>Recursion + Iteration</td>
|
|
1802
|
+
<th>Principle</th>
|
|
1803
|
+
<th>Description</th>
|
|
1010
1804
|
</tr>
|
|
1011
1805
|
<tr>
|
|
1012
|
-
<td>
|
|
1013
|
-
<td>
|
|
1014
|
-
from left to right.
|
|
1015
|
-
</td>
|
|
1016
|
-
<td>Iteration</td>
|
|
1806
|
+
<td>Practicality</td>
|
|
1807
|
+
<td>Follows ES6 and ESNext standards, offering unified and considerate optional parameters, and simplifies method names.</td>
|
|
1017
1808
|
</tr>
|
|
1018
1809
|
<tr>
|
|
1019
|
-
<td>
|
|
1020
|
-
<td>
|
|
1021
|
-
possible, and backtracking to explore other paths. Used for finding connected components, paths, etc.
|
|
1022
|
-
</td>
|
|
1023
|
-
<td>Recursion + Iteration</td>
|
|
1810
|
+
<td>Extensibility</td>
|
|
1811
|
+
<td>Adheres to OOP (Object-Oriented Programming) principles, allowing inheritance for all data structures.</td>
|
|
1024
1812
|
</tr>
|
|
1025
1813
|
<tr>
|
|
1026
|
-
<td>
|
|
1027
|
-
<td>
|
|
1028
|
-
traversal without additional stack or recursion.
|
|
1029
|
-
</td>
|
|
1030
|
-
<td>Iteration</td>
|
|
1814
|
+
<td>Modularization</td>
|
|
1815
|
+
<td>Includes data structure modularization and independent NPM packages.</td>
|
|
1031
1816
|
</tr>
|
|
1032
1817
|
<tr>
|
|
1033
|
-
<td>
|
|
1034
|
-
<td>
|
|
1035
|
-
to the starting node, and then expanding level by level. Used for finding shortest paths, etc.
|
|
1036
|
-
</td>
|
|
1037
|
-
<td>Recursion + Iteration</td>
|
|
1818
|
+
<td>Efficiency</td>
|
|
1819
|
+
<td>All methods provide time and space complexity, comparable to native JS performance.</td>
|
|
1038
1820
|
</tr>
|
|
1039
1821
|
<tr>
|
|
1040
|
-
<td>
|
|
1041
|
-
<td>
|
|
1042
|
-
<td>Recursion</td>
|
|
1822
|
+
<td>Maintainability</td>
|
|
1823
|
+
<td>Follows open-source community development standards, complete documentation, continuous integration, and adheres to TDD (Test-Driven Development) patterns.</td>
|
|
1043
1824
|
</tr>
|
|
1044
1825
|
<tr>
|
|
1045
|
-
<td>
|
|
1046
|
-
<td>
|
|
1047
|
-
<td>Iteration</td>
|
|
1826
|
+
<td>Testability</td>
|
|
1827
|
+
<td>Automated and customized unit testing, performance testing, and integration testing.</td>
|
|
1048
1828
|
</tr>
|
|
1049
1829
|
<tr>
|
|
1050
|
-
<td>
|
|
1051
|
-
<td>
|
|
1052
|
-
<td>Iteration</td>
|
|
1830
|
+
<td>Portability</td>
|
|
1831
|
+
<td>Plans for porting to Java, Python, and C++, currently achieved to 80%.</td>
|
|
1053
1832
|
</tr>
|
|
1054
1833
|
<tr>
|
|
1055
|
-
<td>
|
|
1056
|
-
<td>
|
|
1057
|
-
<td>Iteration</td>
|
|
1834
|
+
<td>Reusability</td>
|
|
1835
|
+
<td>Fully decoupled, minimized side effects, and adheres to OOP.</td>
|
|
1058
1836
|
</tr>
|
|
1059
1837
|
<tr>
|
|
1060
|
-
<td>
|
|
1061
|
-
<td>
|
|
1062
|
-
<td>Recursion</td>
|
|
1838
|
+
<td>Security</td>
|
|
1839
|
+
<td>Carefully designed security for member variables and methods. Read-write separation. Data structure software does not need to consider other security aspects.</td>
|
|
1063
1840
|
</tr>
|
|
1064
1841
|
<tr>
|
|
1065
|
-
<td>
|
|
1066
|
-
<td>
|
|
1067
|
-
the graph.
|
|
1068
|
-
</td>
|
|
1069
|
-
<td>Recursion</td>
|
|
1842
|
+
<td>Scalability</td>
|
|
1843
|
+
<td>Data structure software does not involve load issues.</td>
|
|
1070
1844
|
</tr>
|
|
1071
|
-
<tr>
|
|
1072
|
-
<td>Graph getSCCs</td>
|
|
1073
|
-
<td>Find strongly connected components in a graph, which are subgraphs where any two nodes can reach each other.
|
|
1074
|
-
</td>
|
|
1075
|
-
<td>Recursion</td>
|
|
1076
|
-
</tr>
|
|
1077
|
-
<tr>
|
|
1078
|
-
<td>Graph getBridges</td>
|
|
1079
|
-
<td>Find bridges in a graph, which are edges that, when removed, increase the number of connected components in the
|
|
1080
|
-
graph.
|
|
1081
|
-
</td>
|
|
1082
|
-
<td>Recursion</td>
|
|
1083
|
-
</tr>
|
|
1084
|
-
<tr>
|
|
1085
|
-
<td>Graph topologicalSort</td>
|
|
1086
|
-
<td>Perform topological sorting on a directed acyclic graph (DAG) to find a linear order of nodes such that all
|
|
1087
|
-
directed edges go from earlier nodes to later nodes.
|
|
1088
|
-
</td>
|
|
1089
|
-
<td>Recursion</td>
|
|
1090
|
-
</tr>
|
|
1091
|
-
</tbody>
|
|
1092
1845
|
</table>
|
|
1093
1846
|
|
|
1094
|
-
|
|
1095
|
-
maximum performance on modern engines with broad compatibility for older Node.js
|
|
1096
|
-
and browsers.
|
|
1097
|
-
|
|
1098
|
-
### Build Targets
|
|
1099
|
-
|
|
1100
|
-
| Target | Output | Recommended runtime | Minimum runtime | Notes |
|
|
1101
|
-
|---|---|---:|---:|---|
|
|
1102
|
-
| **Modern (ES2022)** | `dist/esm` / `dist/cjs` | **Node.js 18+** | Node.js 16+ | Best performance. Enables V8 to fully optimize hot paths (JIT-friendly class semantics). |
|
|
1103
|
-
| **Legacy (ES2018)** | `dist/esm-legacy` / `dist/cjs-legacy` | Node.js 16+ | **Node.js 12+** | Maximum compatibility. Slightly slower due to older compilation target and reduced JIT opportunities. |
|
|
1847
|
+
---
|
|
1104
1848
|
|
|
1105
|
-
|
|
1849
|
+
## đ§ TypeScript Support
|
|
1106
1850
|
|
|
1107
|
-
|
|
1108
|
-
(e.g. Red-Black Tree `add/insert`) because it avoids performance overhead from
|
|
1109
|
-
transpiled class field initialization and improves JIT optimization.
|
|
1851
|
+
Full type safety with automatic type inference:
|
|
1110
1852
|
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1853
|
+
```typescript
|
|
1854
|
+
// Generic type parameters
|
|
1855
|
+
const bst = new BST<number, { name: string }>();
|
|
1856
|
+
bst.add(10, { name: 'Alice' });
|
|
1114
1857
|
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
> - We recommend running benchmarks on **Node.js 18+** for stable, modern V8 behavior.
|
|
1858
|
+
// Type-safe retrieval
|
|
1859
|
+
const value: { name: string } | undefined = bst.get(10);
|
|
1118
1860
|
|
|
1119
|
-
|
|
1861
|
+
// Custom comparator
|
|
1862
|
+
const descBST = new BST<number>([], (a, b) => b - a);
|
|
1120
1863
|
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
- **Best experience:** Node.js **20+** (latest V8 improvements)
|
|
1124
|
-
|
|
1125
|
-
If you target Node.js 18+ only, you will get the best performance out of the box.
|
|
1126
|
-
|
|
1127
|
-
### Browser Support
|
|
1128
|
-
|
|
1129
|
-
- **Modern browsers (Evergreen):** use the **Modern (ES2022)** ESM build.
|
|
1130
|
-
- **Older browsers / conservative bundlers:** use the **Legacy (ES2018)** ESM build.
|
|
1131
|
-
|
|
1132
|
-
In most bundler setups, the correct build is resolved automatically via `exports`.
|
|
1133
|
-
If you need to force a specific target, use the explicit entry points:
|
|
1134
|
-
|
|
1135
|
-
```js
|
|
1136
|
-
// Force modern build (ES2022)
|
|
1137
|
-
import { RedBlackTree } from "data-structure-typed/modern";
|
|
1138
|
-
|
|
1139
|
-
// Force legacy build (ES2018)
|
|
1140
|
-
import { RedBlackTree } from "data-structure-typed/legacy";
|
|
1141
|
-
```
|
|
1142
|
-
|
|
1143
|
-
Just run
|
|
1144
|
-
|
|
1145
|
-
```shell
|
|
1146
|
-
pnpm test:perf red-black-tree.test.ts
|
|
1147
|
-
```
|
|
1148
|
-
|
|
1149
|
-
```html
|
|
1150
|
-
1,000,000 add randomly: 1.141s
|
|
1151
|
-
1,000,000 add: 374.859ms
|
|
1152
|
-
1,000,000 get: 5.99ms
|
|
1864
|
+
// Full IDE autocomplete support
|
|
1865
|
+
tree.map(x => x * 2); // TypeScript knows the signature
|
|
1153
1866
|
```
|
|
1154
1867
|
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
We strictly adhere to computer science theory and software development standards. Our LinkedList is designed in the
|
|
1158
|
-
traditional sense of the LinkedList data structure, and we refrain from substituting it with a Deque solely for the
|
|
1159
|
-
purpose of showcasing performance test data. However, we have also implemented a Deque based on a dynamic array
|
|
1160
|
-
concurrently.
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
<table style="display: table; width:100%; table-layout: fixed;">
|
|
1164
|
-
<tr>
|
|
1165
|
-
<th>Principle</th>
|
|
1166
|
-
<th>Description</th>
|
|
1167
|
-
</tr>
|
|
1168
|
-
<tr>
|
|
1169
|
-
<td>Practicality</td>
|
|
1170
|
-
<td>Follows ES6 and ESNext standards, offering unified and considerate optional parameters, and simplifies method names.</td>
|
|
1171
|
-
</tr>
|
|
1172
|
-
<tr>
|
|
1173
|
-
<td>Extensibility</td>
|
|
1174
|
-
<td>Adheres to OOP (Object-Oriented Programming) principles, allowing inheritance for all data structures.</td>
|
|
1175
|
-
</tr>
|
|
1176
|
-
<tr>
|
|
1177
|
-
<td>Modularization</td>
|
|
1178
|
-
<td>Includes data structure modularization and independent NPM packages.</td>
|
|
1179
|
-
</tr>
|
|
1180
|
-
<tr>
|
|
1181
|
-
<td>Efficiency</td>
|
|
1182
|
-
<td>All methods provide time and space complexity, comparable to native JS performance.</td>
|
|
1183
|
-
</tr>
|
|
1184
|
-
<tr>
|
|
1185
|
-
<td>Maintainability</td>
|
|
1186
|
-
<td>Follows open-source community development standards, complete documentation, continuous integration, and adheres to TDD (Test-Driven Development) patterns.</td>
|
|
1187
|
-
</tr>
|
|
1188
|
-
<tr>
|
|
1189
|
-
<td>Testability</td>
|
|
1190
|
-
<td>Automated and customized unit testing, performance testing, and integration testing.</td>
|
|
1191
|
-
</tr>
|
|
1192
|
-
<tr>
|
|
1193
|
-
<td>Portability</td>
|
|
1194
|
-
<td>Plans for porting to Java, Python, and C++, currently achieved to 80%.</td>
|
|
1195
|
-
</tr>
|
|
1196
|
-
<tr>
|
|
1197
|
-
<td>Reusability</td>
|
|
1198
|
-
<td>Fully decoupled, minimized side effects, and adheres to OOP.</td>
|
|
1199
|
-
</tr>
|
|
1200
|
-
<tr>
|
|
1201
|
-
<td>Security</td>
|
|
1202
|
-
<td>Carefully designed security for member variables and methods. Read-write separation. Data structure software does not need to consider other security aspects.</td>
|
|
1203
|
-
</tr>
|
|
1204
|
-
<tr>
|
|
1205
|
-
<td>Scalability</td>
|
|
1206
|
-
<td>Data structure software does not involve load issues.</td>
|
|
1207
|
-
</tr>
|
|
1208
|
-
</table>
|
|
1209
|
-
|
|
1210
|
-
## supported module system
|
|
1211
|
-
|
|
1212
|
-
Now you can use it in Node.js and browser environments
|
|
1213
|
-
|
|
1214
|
-
CommonJS:**`require export.modules =`**
|
|
1215
|
-
|
|
1216
|
-
ESModule: **`import export`**
|
|
1217
|
-
|
|
1218
|
-
Typescript: **`import export`**
|
|
1219
|
-
|
|
1220
|
-
UMD: **`var Deque = dataStructureTyped.Deque`**
|
|
1221
|
-
|
|
1222
|
-
### CDN
|
|
1223
|
-
|
|
1224
|
-
Copy the line below into the head tag in an HTML document.
|
|
1225
|
-
|
|
1226
|
-
#### development
|
|
1227
|
-
|
|
1228
|
-
##### ES Module
|
|
1229
|
-
|
|
1230
|
-
```html
|
|
1868
|
+
---
|
|
1231
1869
|
|
|
1232
|
-
|
|
1233
|
-
import { BST } from "https://cdn.jsdelivr.net/npm/data-structure-typed/dist/esm/index.mjs";
|
|
1870
|
+
## đ Feedback and Contributions
|
|
1234
1871
|
|
|
1235
|
-
|
|
1236
|
-
bst.print();
|
|
1237
|
-
</script>
|
|
1238
|
-
```
|
|
1872
|
+
This library is maintained with care. Found an issue or have a suggestion? We welcome all feedback!
|
|
1239
1873
|
|
|
1240
|
-
|
|
1874
|
+
- **Issues**: [GitHub Issues](https://github.com/zrwusa/data-structure-typed/issues)
|
|
1875
|
+
- **Discussions**: [GitHub Discussions](https://github.com/zrwusa/data-structure-typed/discussions)
|
|
1241
1876
|
|
|
1242
|
-
|
|
1877
|
+
---
|
|
1243
1878
|
|
|
1244
|
-
|
|
1245
|
-
```
|
|
1879
|
+
## đ License
|
|
1246
1880
|
|
|
1247
|
-
|
|
1881
|
+
[MIT License](LICENSE)
|
|
1248
1882
|
|
|
1249
|
-
|
|
1883
|
+
---
|
|
1250
1884
|
|
|
1251
|
-
|
|
1252
|
-
```
|
|
1885
|
+
## đ Thank You
|
|
1253
1886
|
|
|
1254
|
-
|
|
1887
|
+
Thank you for using **data-structure-typed**. We hope it makes your coding journey more productive and enjoyable!
|
|
1255
1888
|
|
|
1256
|
-
|
|
1257
|
-
const { Heap } = dataStructureTyped;
|
|
1258
|
-
const {
|
|
1259
|
-
BinaryTree, Graph, Queue, Stack, PriorityQueue, BST, Trie, DoublyLinkedList,
|
|
1260
|
-
AVLTree, MinHeap, SinglyLinkedList, DirectedGraph, TreeMultiMap,
|
|
1261
|
-
DirectedVertex, AVLTreeNode
|
|
1262
|
-
} = dataStructureTyped;
|
|
1263
|
-
```
|
|
1889
|
+
Happy coding! đ
|