data-structure-typed 2.5.1 → 2.5.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +5 -1
- package/MIGRATION.md +169 -0
- package/README.md +135 -23
- package/README_CN.md +551 -143
- package/SPECIFICATION.md +20 -14
- package/SPECIFICATION.zh-CN.md +20 -14
- package/dist/cjs/binary-tree.cjs +6460 -1591
- package/dist/cjs/graph.cjs +440 -20
- package/dist/cjs/hash.cjs +125 -22
- package/dist/cjs/heap.cjs +196 -47
- package/dist/cjs/index.cjs +8486 -2429
- package/dist/cjs/linked-list.cjs +456 -31
- package/dist/cjs/matrix.cjs +79 -9
- package/dist/cjs/priority-queue.cjs +193 -44
- package/dist/cjs/queue.cjs +391 -2
- package/dist/cjs/stack.cjs +92 -6
- package/dist/cjs/trie.cjs +122 -28
- package/dist/cjs-legacy/binary-tree.cjs +6484 -1612
- package/dist/cjs-legacy/graph.cjs +440 -20
- package/dist/cjs-legacy/hash.cjs +125 -22
- package/dist/cjs-legacy/heap.cjs +196 -47
- package/dist/cjs-legacy/index.cjs +8654 -2594
- package/dist/cjs-legacy/linked-list.cjs +456 -31
- package/dist/cjs-legacy/matrix.cjs +79 -9
- package/dist/cjs-legacy/priority-queue.cjs +193 -44
- package/dist/cjs-legacy/queue.cjs +391 -2
- package/dist/cjs-legacy/stack.cjs +92 -6
- package/dist/cjs-legacy/trie.cjs +122 -28
- package/dist/esm/binary-tree.mjs +6460 -1591
- package/dist/esm/graph.mjs +440 -20
- package/dist/esm/hash.mjs +125 -22
- package/dist/esm/heap.mjs +196 -47
- package/dist/esm/index.mjs +8486 -2430
- package/dist/esm/linked-list.mjs +456 -31
- package/dist/esm/matrix.mjs +79 -9
- package/dist/esm/priority-queue.mjs +193 -44
- package/dist/esm/queue.mjs +391 -2
- package/dist/esm/stack.mjs +92 -6
- package/dist/esm/trie.mjs +122 -28
- package/dist/esm-legacy/binary-tree.mjs +6484 -1612
- package/dist/esm-legacy/graph.mjs +440 -20
- package/dist/esm-legacy/hash.mjs +125 -22
- package/dist/esm-legacy/heap.mjs +196 -47
- package/dist/esm-legacy/index.mjs +8654 -2595
- package/dist/esm-legacy/linked-list.mjs +456 -31
- package/dist/esm-legacy/matrix.mjs +79 -9
- package/dist/esm-legacy/priority-queue.mjs +193 -44
- package/dist/esm-legacy/queue.mjs +391 -2
- package/dist/esm-legacy/stack.mjs +92 -6
- package/dist/esm-legacy/trie.mjs +122 -28
- package/dist/types/common/error.d.ts +9 -0
- package/dist/types/common/index.d.ts +1 -1
- package/dist/types/data-structures/binary-tree/avl-tree.d.ts +98 -2
- package/dist/types/data-structures/binary-tree/binary-indexed-tree.d.ts +112 -0
- package/dist/types/data-structures/binary-tree/binary-tree.d.ts +214 -13
- package/dist/types/data-structures/binary-tree/bst.d.ts +294 -3
- package/dist/types/data-structures/binary-tree/red-black-tree.d.ts +155 -8
- package/dist/types/data-structures/binary-tree/segment-tree.d.ts +48 -0
- package/dist/types/data-structures/binary-tree/tree-map.d.ts +1370 -323
- package/dist/types/data-structures/binary-tree/tree-multi-map.d.ts +1329 -316
- package/dist/types/data-structures/binary-tree/tree-multi-set.d.ts +1116 -295
- package/dist/types/data-structures/binary-tree/tree-set.d.ts +1330 -326
- package/dist/types/data-structures/graph/directed-graph.d.ts +80 -0
- package/dist/types/data-structures/graph/undirected-graph.d.ts +72 -0
- package/dist/types/data-structures/hash/hash-map.d.ts +95 -6
- package/dist/types/data-structures/heap/heap.d.ts +154 -12
- package/dist/types/data-structures/linked-list/doubly-linked-list.d.ts +143 -0
- package/dist/types/data-structures/linked-list/singly-linked-list.d.ts +121 -1
- package/dist/types/data-structures/linked-list/skip-linked-list.d.ts +144 -0
- package/dist/types/data-structures/matrix/matrix.d.ts +64 -0
- package/dist/types/data-structures/queue/deque.d.ts +142 -0
- package/dist/types/data-structures/queue/queue.d.ts +109 -0
- package/dist/types/data-structures/stack/stack.d.ts +82 -2
- package/dist/types/data-structures/trie/trie.d.ts +96 -0
- package/dist/types/interfaces/binary-tree.d.ts +2 -3
- package/dist/types/types/data-structures/binary-tree/bst.d.ts +1 -0
- package/dist/types/types/data-structures/binary-tree/tree-map.d.ts +5 -0
- package/dist/types/types/data-structures/binary-tree/tree-multi-set.d.ts +4 -0
- package/dist/types/types/data-structures/binary-tree/tree-set.d.ts +4 -0
- package/dist/umd/data-structure-typed.js +8623 -2564
- package/dist/umd/data-structure-typed.min.js +5 -5
- package/docs-site-docusaurus/docs/api/classes/AVLTree.md +696 -194
- package/docs-site-docusaurus/docs/api/classes/AVLTreeNode.md +11 -11
- package/docs-site-docusaurus/docs/api/classes/AbstractGraph.md +71 -71
- package/docs-site-docusaurus/docs/api/classes/BST.md +639 -189
- package/docs-site-docusaurus/docs/api/classes/BSTNode.md +13 -13
- package/docs-site-docusaurus/docs/api/classes/BinaryIndexedTree.md +15 -15
- package/docs-site-docusaurus/docs/api/classes/BinaryTree.md +148 -160
- package/docs-site-docusaurus/docs/api/classes/BinaryTreeNode.md +13 -13
- package/docs-site-docusaurus/docs/api/classes/Deque.md +105 -91
- package/docs-site-docusaurus/docs/api/classes/DirectedGraph.md +82 -82
- package/docs-site-docusaurus/docs/api/classes/DoublyLinkedList.md +104 -74
- package/docs-site-docusaurus/docs/api/classes/DoublyLinkedListNode.md +8 -8
- package/docs-site-docusaurus/docs/api/classes/FibonacciHeap.md +12 -12
- package/docs-site-docusaurus/docs/api/classes/FibonacciHeapNode.md +1 -1
- package/docs-site-docusaurus/docs/api/classes/HashMap.md +51 -51
- package/docs-site-docusaurus/docs/api/classes/Heap.md +96 -85
- package/docs-site-docusaurus/docs/api/classes/IterableElementBase.md +25 -25
- package/docs-site-docusaurus/docs/api/classes/IterableEntryBase.md +33 -33
- package/docs-site-docusaurus/docs/api/classes/LinearBase.md +50 -50
- package/docs-site-docusaurus/docs/api/classes/LinearLinkedBase.md +55 -55
- package/docs-site-docusaurus/docs/api/classes/LinkedHashMap.md +55 -55
- package/docs-site-docusaurus/docs/api/classes/LinkedListNode.md +6 -6
- package/docs-site-docusaurus/docs/api/classes/LinkedListQueue.md +78 -78
- package/docs-site-docusaurus/docs/api/classes/MapGraph.md +82 -82
- package/docs-site-docusaurus/docs/api/classes/Matrix.md +31 -31
- package/docs-site-docusaurus/docs/api/classes/MaxHeap.md +104 -89
- package/docs-site-docusaurus/docs/api/classes/MaxPriorityQueue.md +104 -89
- package/docs-site-docusaurus/docs/api/classes/MinHeap.md +104 -89
- package/docs-site-docusaurus/docs/api/classes/MinPriorityQueue.md +104 -89
- package/docs-site-docusaurus/docs/api/classes/Navigator.md +5 -5
- package/docs-site-docusaurus/docs/api/classes/PriorityQueue.md +103 -88
- package/docs-site-docusaurus/docs/api/classes/Queue.md +112 -60
- package/docs-site-docusaurus/docs/api/classes/RedBlackTree.md +708 -206
- package/docs-site-docusaurus/docs/api/classes/SegmentTree.md +10 -10
- package/docs-site-docusaurus/docs/api/classes/SinglyLinkedList.md +79 -79
- package/docs-site-docusaurus/docs/api/classes/SinglyLinkedListNode.md +6 -6
- package/docs-site-docusaurus/docs/api/classes/SkipList.md +44 -44
- package/docs-site-docusaurus/docs/api/classes/Stack.md +42 -42
- package/docs-site-docusaurus/docs/api/classes/TreeMap.md +236 -33
- package/docs-site-docusaurus/docs/api/classes/TreeMultiMap.md +162 -46
- package/docs-site-docusaurus/docs/api/classes/TreeSet.md +232 -32
- package/docs-site-docusaurus/docs/api/classes/Trie.md +47 -47
- package/docs-site-docusaurus/docs/api/classes/TrieNode.md +8 -8
- package/docs-site-docusaurus/docs/api/classes/UndirectedGraph.md +81 -81
- package/docs-site-docusaurus/docs/guide/architecture.md +75 -5
- package/docs-site-docusaurus/docs/guide/concepts.md +53 -3
- package/docs-site-docusaurus/docs/guide/faq.md +233 -0
- package/docs-site-docusaurus/docs/guide/guides.md +43 -58
- package/docs-site-docusaurus/docs/guide/installation.md +2 -0
- package/docs-site-docusaurus/docs/guide/integrations.md +75 -176
- package/docs-site-docusaurus/docs/guide/overview.md +132 -11
- package/docs-site-docusaurus/docs/guide/performance.md +2 -0
- package/docs-site-docusaurus/docs/guide/quick-start.md +31 -0
- package/docs-site-docusaurus/docs/guide/use-cases/_category_.json +6 -0
- package/docs-site-docusaurus/docs/guide/use-cases/array-sort-alternative.md +158 -0
- package/docs-site-docusaurus/docs/guide/use-cases/heap-vs-sorting.md +92 -0
- package/docs-site-docusaurus/docs/guide/use-cases/map-vs-treemap.md +151 -0
- package/docs-site-docusaurus/docs/guide/use-cases/priority-queue-typescript.md +113 -0
- package/docs-site-docusaurus/docs/guide/use-cases/treemap-javascript.md +151 -0
- package/docs-site-docusaurus/docusaurus.config.ts +1 -1
- package/docs-site-docusaurus/src/pages/index.tsx +55 -2
- package/docs-site-docusaurus/static/llms.txt +37 -0
- package/docs-site-docusaurus/typedoc.json +1 -0
- package/llms.txt +37 -0
- package/package.json +65 -56
- package/src/common/error.ts +19 -1
- package/src/common/index.ts +1 -1
- package/src/data-structures/base/iterable-element-base.ts +3 -2
- package/src/data-structures/binary-tree/avl-tree.ts +99 -5
- package/src/data-structures/binary-tree/binary-indexed-tree.ts +102 -4
- package/src/data-structures/binary-tree/binary-tree.ts +239 -78
- package/src/data-structures/binary-tree/bst.ts +542 -13
- package/src/data-structures/binary-tree/red-black-tree.ts +155 -15
- package/src/data-structures/binary-tree/segment-tree.ts +42 -0
- package/src/data-structures/binary-tree/tree-map.ts +1223 -261
- package/src/data-structures/binary-tree/tree-multi-map.ts +939 -30
- package/src/data-structures/binary-tree/tree-multi-set.ts +746 -10
- package/src/data-structures/binary-tree/tree-set.ts +1018 -99
- package/src/data-structures/graph/abstract-graph.ts +2 -2
- package/src/data-structures/graph/directed-graph.ts +71 -1
- package/src/data-structures/graph/undirected-graph.ts +64 -1
- package/src/data-structures/hash/hash-map.ts +102 -16
- package/src/data-structures/heap/heap.ts +153 -23
- package/src/data-structures/heap/max-heap.ts +2 -2
- package/src/data-structures/linked-list/doubly-linked-list.ts +139 -0
- package/src/data-structures/linked-list/singly-linked-list.ts +106 -1
- package/src/data-structures/linked-list/skip-linked-list.ts +131 -5
- package/src/data-structures/matrix/matrix.ts +65 -9
- package/src/data-structures/priority-queue/max-priority-queue.ts +2 -2
- package/src/data-structures/queue/deque.ts +130 -0
- package/src/data-structures/queue/queue.ts +109 -0
- package/src/data-structures/stack/stack.ts +75 -5
- package/src/data-structures/trie/trie.ts +86 -2
- package/src/interfaces/binary-tree.ts +1 -9
- package/src/types/data-structures/binary-tree/bst.ts +1 -0
- package/src/types/data-structures/binary-tree/tree-map.ts +6 -0
- package/src/types/data-structures/binary-tree/tree-multi-set.ts +5 -0
- package/src/types/data-structures/binary-tree/tree-set.ts +5 -0
- package/.vitepress/cache/deps_temp_51f5f1b0/chunk-7OIKW5WK.js +0 -12984
- package/.vitepress/cache/deps_temp_51f5f1b0/package.json +0 -3
- package/.vitepress/cache/deps_temp_51f5f1b0/vitepress___@vue_devtools-api.js +0 -4505
- package/.vitepress/cache/deps_temp_51f5f1b0/vitepress___@vueuse_core.js +0 -9731
- package/.vitepress/cache/deps_temp_51f5f1b0/vue.js +0 -347
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
---
|
|
2
2
|
sidebar_label: "INTEGRATIONS"
|
|
3
3
|
description: "Integrate data-structure-typed with React, Express, NestJS, and other frameworks. Production-ready patterns."
|
|
4
|
+
title: "Framework Integrations — React, Express, NestJS"
|
|
5
|
+
keywords: ["data-structure-typed react", "typescript data structures express", "nestjs data structures", "production patterns"]
|
|
4
6
|
---
|
|
5
|
-
|
|
6
7
|
# INTEGRATIONS
|
|
7
8
|
|
|
8
9
|
How to use data-structure-typed with React, Express, Nest.js, and other frameworks.
|
|
9
10
|
|
|
10
|
-
**[Back to README](
|
|
11
|
+
**[Back to README](/docs/guide/quick-start) • [Code Examples](/guide/guides.md) • [Performance](/guide/performance.md)**
|
|
11
12
|
|
|
12
13
|
---
|
|
13
14
|
|
|
@@ -289,6 +290,8 @@ app.get('/api/data', (req, res) => {
|
|
|
289
290
|
|
|
290
291
|
### Use Case: Product Price Index Service
|
|
291
292
|
|
|
293
|
+
> Full working demo: [StackBlitz NestJS Playground](https://stackblitz.com/github/zrwusa/dst-playgrounds/tree/main/apps/nestjs?file=src%2Fproduct%2Fservices%2Fproduct-price-index.service.ts&title=data-structure-typed%20%E2%80%94%20NestJS%20Product%20API)
|
|
294
|
+
|
|
292
295
|
```typescript
|
|
293
296
|
import {
|
|
294
297
|
BadRequestException,
|
|
@@ -307,7 +310,6 @@ export interface Product {
|
|
|
307
310
|
lastUpdated?: Date;
|
|
308
311
|
}
|
|
309
312
|
|
|
310
|
-
/** KEY INSIGHT: Use compound keys to solve the problem of "multiple products at the same price" */
|
|
311
313
|
interface CompositeKey {
|
|
312
314
|
price: number;
|
|
313
315
|
productId: string;
|
|
@@ -326,13 +328,8 @@ export type TierName = 'budget' | 'mid-range' | 'premium';
|
|
|
326
328
|
* Point Lookup | O(1) | O(1) | O(1)
|
|
327
329
|
* Insert/Update | O(log n) | O(n) | O(log n)
|
|
328
330
|
* Sort by Price | O(n) | O(n log n)| O(n log n)
|
|
329
|
-
*
|
|
330
|
-
*
|
|
331
|
-
* Advantages:
|
|
332
|
-
* - O(1) idToKeyMap lookup + O(log n) tree operations
|
|
333
|
-
* - Automatic ordering without post-sort
|
|
334
|
-
* - Efficient range queries for pricing tiers
|
|
335
|
-
* - Low memory footprint vs duplicate maps
|
|
331
|
+
* Pagination | O(log n + k) | O(n log n)| O(n log n)
|
|
332
|
+
* Rank/Percentile | O(log n) | O(n) | O(n log n)
|
|
336
333
|
*/
|
|
337
334
|
@Injectable()
|
|
338
335
|
export class ProductPriceIndexService {
|
|
@@ -346,228 +343,130 @@ export class ProductPriceIndexService {
|
|
|
346
343
|
if (priceCmp !== 0) return priceCmp;
|
|
347
344
|
return a.productId.localeCompare(b.productId);
|
|
348
345
|
},
|
|
346
|
+
enableOrderStatistic: true, // Enables getRank/getByRank/rangeByRank
|
|
349
347
|
});
|
|
350
348
|
this.idToKeyMap = new Map();
|
|
351
349
|
}
|
|
352
350
|
|
|
353
|
-
/**
|
|
351
|
+
/** O(log n) */
|
|
354
352
|
addProduct(product: Product): Product {
|
|
355
353
|
if (this.idToKeyMap.has(product.id))
|
|
356
354
|
throw new BadRequestException(`Product ${product.id} already exists`);
|
|
357
355
|
|
|
358
356
|
product.lastUpdated = new Date();
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
price: product.price,
|
|
362
|
-
productId: product.id,
|
|
363
|
-
};
|
|
364
|
-
|
|
365
|
-
this.priceIndex.add(key, product);
|
|
357
|
+
const key: CompositeKey = { price: product.price, productId: product.id };
|
|
358
|
+
this.priceIndex.set(key, product);
|
|
366
359
|
this.idToKeyMap.set(product.id, key);
|
|
367
|
-
|
|
368
360
|
return product;
|
|
369
361
|
}
|
|
370
362
|
|
|
371
|
-
/**
|
|
372
|
-
updateProduct(productId: string, updates: Partial<Product>): Product {
|
|
373
|
-
const oldKey = this.idToKeyMap.get(productId);
|
|
374
|
-
if (oldKey === undefined)
|
|
375
|
-
throw new NotFoundException(`Product ${productId} not found`);
|
|
376
|
-
|
|
377
|
-
const existing = this.priceIndex.get(oldKey);
|
|
378
|
-
if (!existing)
|
|
379
|
-
throw new NotFoundException(`Product ${productId} not found`);
|
|
380
|
-
|
|
381
|
-
const updated: Product = {
|
|
382
|
-
...existing,
|
|
383
|
-
...updates,
|
|
384
|
-
id: existing.id,
|
|
385
|
-
lastUpdated: new Date(),
|
|
386
|
-
};
|
|
387
|
-
|
|
388
|
-
const newPrice = updates.price ?? existing.price;
|
|
389
|
-
|
|
390
|
-
this.priceIndex.delete(oldKey);
|
|
391
|
-
const currentKey: CompositeKey = {
|
|
392
|
-
price: newPrice,
|
|
393
|
-
productId,
|
|
394
|
-
};
|
|
395
|
-
this.priceIndex.set(currentKey, updated);
|
|
396
|
-
this.idToKeyMap.set(productId, currentKey);
|
|
397
|
-
|
|
398
|
-
return updated;
|
|
399
|
-
}
|
|
400
|
-
|
|
401
|
-
/** Time Complexity: O(1) */
|
|
363
|
+
/** O(1) — HashMap lookup */
|
|
402
364
|
getProductById(productId: string): Product {
|
|
403
365
|
const key = this.idToKeyMap.get(productId);
|
|
404
|
-
|
|
405
366
|
if (key === undefined)
|
|
406
367
|
throw new NotFoundException(`Product ${productId} not found`);
|
|
407
|
-
|
|
408
368
|
return this.priceIndex.get(key)!;
|
|
409
369
|
}
|
|
410
370
|
|
|
411
|
-
/**
|
|
371
|
+
/** O(log n + k) — directly returns values, no secondary lookup */
|
|
412
372
|
getProductsByPriceRange(minPrice: number, maxPrice: number): Product[] {
|
|
413
373
|
const range = new Range(
|
|
414
374
|
{ price: minPrice, productId: '' },
|
|
415
375
|
{ price: maxPrice, productId: '\uffff' },
|
|
416
|
-
true,
|
|
417
|
-
true,
|
|
376
|
+
true,
|
|
377
|
+
true,
|
|
418
378
|
);
|
|
419
|
-
|
|
420
|
-
const keys = this.priceIndex.rangeSearch(range, (n) => n.key);
|
|
421
|
-
return keys.map((key) => this.priceIndex.get(key)!);
|
|
379
|
+
return this.priceIndex.rangeSearch(range, (n) => n.value!);
|
|
422
380
|
}
|
|
423
381
|
|
|
424
|
-
/**
|
|
382
|
+
/** O(log n) — NavigableMap floor() */
|
|
425
383
|
getHighestPricedProductWithinBudget(maxBudget: number): Product | null {
|
|
426
|
-
const key: CompositeKey = {
|
|
427
|
-
price: maxBudget,
|
|
428
|
-
productId: '\uffff',
|
|
429
|
-
};
|
|
384
|
+
const key: CompositeKey = { price: maxBudget, productId: '\uffff' };
|
|
430
385
|
const floorKey = this.priceIndex.floor(key);
|
|
431
386
|
return floorKey ? this.priceIndex.get(floorKey)! : null;
|
|
432
387
|
}
|
|
433
388
|
|
|
434
|
-
/**
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
price: minPrice,
|
|
438
|
-
productId: '\uffff',
|
|
439
|
-
};
|
|
440
|
-
const higherKey = this.priceIndex.higher(key);
|
|
441
|
-
return higherKey ? this.priceIndex.get(higherKey)! : null;
|
|
442
|
-
}
|
|
443
|
-
|
|
444
|
-
/** Time Complexity: O(log n + k) */
|
|
445
|
-
getProductsByTier(tierName: TierName): Product[] {
|
|
446
|
-
const tiers = {
|
|
447
|
-
budget: [0, 50],
|
|
448
|
-
'mid-range': [50, 200],
|
|
449
|
-
premium: [200, Infinity],
|
|
450
|
-
};
|
|
451
|
-
|
|
452
|
-
const [min, max] = tiers[tierName];
|
|
453
|
-
return this.getProductsByPriceRange(min, max);
|
|
454
|
-
}
|
|
455
|
-
|
|
456
|
-
/** Time Complexity: O(log n + k + m) */
|
|
457
|
-
getProductsByPriceAndCategory(
|
|
458
|
-
minPrice: number,
|
|
459
|
-
maxPrice: number,
|
|
460
|
-
category: string,
|
|
461
|
-
): Product[] {
|
|
462
|
-
const priceRangeProducts = this.getProductsByPriceRange(minPrice, maxPrice);
|
|
463
|
-
return priceRangeProducts.filter(
|
|
464
|
-
(p) => p.category.toLowerCase() === category.toLowerCase(),
|
|
465
|
-
);
|
|
466
|
-
}
|
|
467
|
-
|
|
468
|
-
/** Time Complexity: O((log n + k) * log n) */
|
|
469
|
-
applyDiscountToRange(
|
|
470
|
-
minPrice: number,
|
|
471
|
-
maxPrice: number,
|
|
472
|
-
discountPercent: number,
|
|
473
|
-
): Product[] {
|
|
474
|
-
const products = this.getProductsByPriceRange(minPrice, maxPrice);
|
|
475
|
-
const updated: Product[] = [];
|
|
476
|
-
|
|
477
|
-
for (const product of products) {
|
|
478
|
-
const newPrice = product.price * (1 - discountPercent / 100);
|
|
479
|
-
const updatedProduct = this.updateProduct(product.id, {
|
|
480
|
-
price: newPrice,
|
|
481
|
-
});
|
|
482
|
-
updated.push(updatedProduct);
|
|
483
|
-
}
|
|
484
|
-
|
|
485
|
-
return updated;
|
|
389
|
+
/** O(n) — iterator protocol, one-liner */
|
|
390
|
+
getAllProductsSortedByPrice(): Product[] {
|
|
391
|
+
return [...this.priceIndex.values()];
|
|
486
392
|
}
|
|
487
393
|
|
|
488
|
-
/**
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
this.priceIndex.delete(key);
|
|
496
|
-
this.idToKeyMap.delete(productId);
|
|
497
|
-
}
|
|
394
|
+
/**
|
|
395
|
+
* O(n) for totalValue, O(log n) for min/max
|
|
396
|
+
* min/max use getLeftMost/getRightMost instead of full traversal
|
|
397
|
+
*/
|
|
398
|
+
getStatistics() {
|
|
399
|
+
if (this.idToKeyMap.size === 0)
|
|
400
|
+
return { totalProducts: 0, priceRange: { min: 0, max: 0 }, averagePrice: 0, totalValue: 0 };
|
|
498
401
|
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
totalProducts: number;
|
|
502
|
-
priceRange: { min: number; max: number };
|
|
503
|
-
averagePrice: number;
|
|
504
|
-
totalValue: number;
|
|
505
|
-
} {
|
|
506
|
-
if (this.idToKeyMap.size === 0) {
|
|
507
|
-
return {
|
|
508
|
-
totalProducts: 0,
|
|
509
|
-
priceRange: { min: 0, max: 0 },
|
|
510
|
-
averagePrice: 0,
|
|
511
|
-
totalValue: 0,
|
|
512
|
-
};
|
|
513
|
-
}
|
|
402
|
+
const minKey = this.priceIndex.getLeftMost();
|
|
403
|
+
const maxKey = this.priceIndex.getRightMost();
|
|
514
404
|
|
|
515
|
-
let minPrice = Infinity;
|
|
516
|
-
let maxPrice = -Infinity;
|
|
517
405
|
let totalValue = 0;
|
|
518
406
|
let totalProducts = 0;
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
while (entry) {
|
|
523
|
-
const product = this.priceIndex.get(entry.key);
|
|
524
|
-
if (product) {
|
|
525
|
-
minPrice = Math.min(minPrice, product.price);
|
|
526
|
-
maxPrice = Math.max(maxPrice, product.price);
|
|
527
|
-
totalValue += product.price * product.quantity;
|
|
528
|
-
totalProducts += product.quantity;
|
|
529
|
-
}
|
|
530
|
-
|
|
531
|
-
entry = this.priceIndex.higher(entry.key, (node) => node);
|
|
407
|
+
for (const [, product] of this.priceIndex) {
|
|
408
|
+
totalValue += product.price * product.quantity;
|
|
409
|
+
totalProducts += product.quantity;
|
|
532
410
|
}
|
|
533
411
|
|
|
534
412
|
return {
|
|
535
|
-
totalProducts
|
|
536
|
-
priceRange: { min:
|
|
413
|
+
totalProducts,
|
|
414
|
+
priceRange: { min: minKey?.price ?? 0, max: maxKey?.price ?? 0 },
|
|
537
415
|
averagePrice: totalValue / totalProducts,
|
|
538
416
|
totalValue,
|
|
539
417
|
};
|
|
540
418
|
}
|
|
541
419
|
|
|
542
|
-
|
|
543
|
-
getAllProductsSortedByPrice(): Product[] {
|
|
544
|
-
const products: Product[] = [];
|
|
545
|
-
let curNode = this.priceIndex.getLeftMost((node) => node);
|
|
420
|
+
// ── Order-Statistic API (rank-based queries) ──────────────────────
|
|
546
421
|
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
422
|
+
/** O(log n + pageSize) — rank-based pagination */
|
|
423
|
+
getProductsByPage(page: number, pageSize: number): Product[] {
|
|
424
|
+
const start = page * pageSize;
|
|
425
|
+
const end = Math.min(start + pageSize - 1, this.priceIndex.size - 1);
|
|
426
|
+
if (start >= this.priceIndex.size) return [];
|
|
427
|
+
const keys = this.priceIndex.rangeByRank(start, end);
|
|
428
|
+
return keys.map((key) => this.priceIndex.get(key)!);
|
|
429
|
+
}
|
|
551
430
|
|
|
552
|
-
|
|
431
|
+
/** O(log n) — what % of products are cheaper */
|
|
432
|
+
getPricePercentile(productId: string): number {
|
|
433
|
+
const key = this.idToKeyMap.get(productId);
|
|
434
|
+
if (!key) throw new NotFoundException(`Product ${productId} not found`);
|
|
435
|
+
return (this.priceIndex.getRank(key) / this.priceIndex.size) * 100;
|
|
553
436
|
}
|
|
554
437
|
|
|
555
|
-
/** O(
|
|
556
|
-
|
|
557
|
-
|
|
438
|
+
/** O(log n) — median product */
|
|
439
|
+
getMedianProduct(): Product | null {
|
|
440
|
+
if (this.priceIndex.size === 0) return null;
|
|
441
|
+
const key = this.priceIndex.getByRank(Math.floor((this.priceIndex.size - 1) / 2));
|
|
442
|
+
return key ? this.priceIndex.get(key)! : null;
|
|
558
443
|
}
|
|
559
444
|
|
|
560
|
-
/** O(
|
|
561
|
-
|
|
562
|
-
|
|
445
|
+
/** O(log n + k) — top N cheapest */
|
|
446
|
+
getTopNCheapest(n: number): Product[] {
|
|
447
|
+
const end = Math.min(n - 1, this.priceIndex.size - 1);
|
|
448
|
+
if (end < 0) return [];
|
|
449
|
+
return this.priceIndex.rangeByRank(0, end).map((key) => this.priceIndex.get(key)!);
|
|
563
450
|
}
|
|
564
451
|
|
|
565
|
-
/** O(n) */
|
|
566
|
-
|
|
567
|
-
|
|
452
|
+
/** O(log n + k) — top N most expensive */
|
|
453
|
+
getTopNExpensive(n: number): Product[] {
|
|
454
|
+
const size = this.priceIndex.size;
|
|
455
|
+
if (size === 0) return [];
|
|
456
|
+
const start = Math.max(size - n, 0);
|
|
457
|
+
return this.priceIndex.rangeByRank(start, size - 1)
|
|
458
|
+
.map((key) => this.priceIndex.get(key)!)
|
|
459
|
+
.reverse();
|
|
568
460
|
}
|
|
569
|
-
}
|
|
570
461
|
|
|
462
|
+
/** O(log n) — dynamic tier by percentile, no hardcoded price ranges */
|
|
463
|
+
getTierByPercentile(productId: string): TierName {
|
|
464
|
+
const pct = this.getPricePercentile(productId);
|
|
465
|
+
if (pct < 33) return 'budget';
|
|
466
|
+
if (pct < 66) return 'mid-range';
|
|
467
|
+
return 'premium';
|
|
468
|
+
}
|
|
469
|
+
}
|
|
571
470
|
```
|
|
572
471
|
|
|
573
472
|
### Use Case: Task Queue Controller
|
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
---
|
|
2
2
|
sidebar_label: "OVERVIEW"
|
|
3
3
|
description: "Complete overview of all 20+ data structures: trees, heaps, graphs, queues, linked lists, hash maps, and more."
|
|
4
|
+
title: "Data Structures Overview — Trees, Heaps, Graphs, Queues"
|
|
5
|
+
keywords: ["typescript data structures overview", "red black tree", "heap", "priority queue", "trie", "graph", "deque", "treemap", "treeset"]
|
|
4
6
|
---
|
|
5
|
-
|
|
6
7
|
# OVERVIEW
|
|
7
8
|
|
|
8
9
|
A quick-reference guide to all structures, common operations, and usage patterns. For complete API details with method signatures and examples, see the **[Full API Docs](https://data-structure-typed-docs.vercel.app/)**.
|
|
9
10
|
|
|
10
|
-
**[Back to README](
|
|
11
|
+
**[Back to README](/docs/guide/quick-start) • [API Docs](https://data-structure-typed-docs.vercel.app/) • [Real-World Examples](/guide/guides.md) • [Performance](/guide/performance.md)**
|
|
11
12
|
|
|
12
13
|
---
|
|
13
14
|
|
|
@@ -55,7 +56,7 @@ A quick-reference guide to all structures, common operations, and usage patterns
|
|
|
55
56
|
import { Stack } from 'data-structure-typed';
|
|
56
57
|
|
|
57
58
|
const stack = new Stack<number>([1, 2]);
|
|
58
|
-
stack.push(3); // add to
|
|
59
|
+
stack.push(3); // add to top
|
|
59
60
|
const top = stack.pop(); // Remove from top - O(1)
|
|
60
61
|
const peek = stack.peek(); // View top
|
|
61
62
|
stack.print(); // [1, 2]
|
|
@@ -166,6 +167,97 @@ avl.print()
|
|
|
166
167
|
// 4 9
|
|
167
168
|
```
|
|
168
169
|
|
|
170
|
+
#### TreeMap (Ordered Map)
|
|
171
|
+
|
|
172
|
+
```typescript
|
|
173
|
+
import { TreeMap } from 'data-structure-typed';
|
|
174
|
+
|
|
175
|
+
const tm = new TreeMap<number, string>([[3, 'c'], [1, 'a'], [2, 'b']]);
|
|
176
|
+
tm.set(4, 'd'); // Set key-value - O(log n)
|
|
177
|
+
tm.get(2); // 'b' - O(log n)
|
|
178
|
+
tm.has(3); // true
|
|
179
|
+
tm.delete(1); // Remove - O(log n)
|
|
180
|
+
|
|
181
|
+
// Navigation — Java NavigableMap-style
|
|
182
|
+
tm.first(); // [2, 'b'] — smallest entry
|
|
183
|
+
tm.last(); // [4, 'd'] — largest entry
|
|
184
|
+
tm.ceiling(3); // [3, 'c'] — smallest >= 3
|
|
185
|
+
tm.floor(2); // [2, 'b'] — largest <= 2
|
|
186
|
+
tm.higher(2); // [3, 'c'] — strictly > 2
|
|
187
|
+
tm.lower(3); // [2, 'b'] — strictly < 3
|
|
188
|
+
|
|
189
|
+
// Iteration (sorted order)
|
|
190
|
+
console.log([...tm.keys()]); // [2, 3, 4]
|
|
191
|
+
console.log([...tm.values()]); // ['b', 'c', 'd']
|
|
192
|
+
|
|
193
|
+
// Bulk operations
|
|
194
|
+
tm.setMany([[5, 'e'], [6, 'f']]); // Set multiple at once
|
|
195
|
+
|
|
196
|
+
// Functional
|
|
197
|
+
const filtered = tm.filter((v, k) => k > 2);
|
|
198
|
+
const mapped = tm.map((v, k) => [k * 10, v!.toUpperCase()] as [number, string]);
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
#### TreeSet (Ordered Set)
|
|
202
|
+
|
|
203
|
+
```typescript
|
|
204
|
+
import { TreeSet } from 'data-structure-typed';
|
|
205
|
+
|
|
206
|
+
const ts = new TreeSet<number>([5, 3, 8, 1]);
|
|
207
|
+
ts.add(4); // Add - O(log n)
|
|
208
|
+
ts.has(3); // true
|
|
209
|
+
ts.delete(5); // Remove - O(log n)
|
|
210
|
+
|
|
211
|
+
// Navigation
|
|
212
|
+
ts.first(); // 1
|
|
213
|
+
ts.last(); // 8
|
|
214
|
+
ts.ceiling(4); // 4 — smallest >= 4
|
|
215
|
+
ts.floor(6); // 4 — largest <= 6
|
|
216
|
+
ts.higher(3); // 4 — strictly > 3
|
|
217
|
+
ts.lower(4); // 3 — strictly < 4
|
|
218
|
+
|
|
219
|
+
// Iteration (sorted order)
|
|
220
|
+
console.log([...ts.keys()]); // [1, 3, 4, 8]
|
|
221
|
+
|
|
222
|
+
// Bulk operations
|
|
223
|
+
ts.addMany([10, 20, 30]); // Add multiple at once
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
#### Order-Statistic Tree (Rank Queries)
|
|
227
|
+
|
|
228
|
+
Enable `enableOrderStatistic: true` on any tree-based structure to get O(log n) rank operations:
|
|
229
|
+
|
|
230
|
+
```typescript
|
|
231
|
+
import { RedBlackTree, TreeMap, TreeSet } from 'data-structure-typed';
|
|
232
|
+
|
|
233
|
+
// Works with RedBlackTree, TreeMap, TreeSet, TreeMultiMap, TreeMultiSet
|
|
234
|
+
const tree = new RedBlackTree<number, string>(
|
|
235
|
+
[[100, 'Alice'], [85, 'Bob'], [92, 'Charlie'], [78, 'Diana']],
|
|
236
|
+
{ comparator: (a, b) => b - a, enableOrderStatistic: true }
|
|
237
|
+
);
|
|
238
|
+
|
|
239
|
+
// getByRank(k) — element at position k in tree order, O(log n)
|
|
240
|
+
tree.getByRank(0); // 100 (1st in tree order)
|
|
241
|
+
tree.getByRank(2); // 92 (3rd in tree order)
|
|
242
|
+
|
|
243
|
+
// getRank(key) — count of elements before key in tree order, O(log n)
|
|
244
|
+
tree.getRank(92); // 2
|
|
245
|
+
|
|
246
|
+
// rangeByRank(start, end) — elements between positions, O(log n + k)
|
|
247
|
+
tree.rangeByRank(0, 2); // [100, 92, 85] — positions 0..2
|
|
248
|
+
|
|
249
|
+
// Also works with wrapper classes
|
|
250
|
+
const tm = new TreeMap<number, string>([], { enableOrderStatistic: true });
|
|
251
|
+
tm.set(10, 'a'); tm.set(20, 'b'); tm.set(30, 'c');
|
|
252
|
+
tm.getByRank(1); // [20, 'b']
|
|
253
|
+
tm.getRank(20); // 1
|
|
254
|
+
|
|
255
|
+
const ts = new TreeSet<number>([], { enableOrderStatistic: true });
|
|
256
|
+
ts.addMany([10, 20, 30]);
|
|
257
|
+
ts.getByRank(0); // 10
|
|
258
|
+
ts.getRank(30); // 2
|
|
259
|
+
```
|
|
260
|
+
|
|
169
261
|
### Heap & Priority Queue
|
|
170
262
|
|
|
171
263
|
#### Heap
|
|
@@ -184,7 +276,9 @@ const peek = minHeap.peek(); // View minimum - O(1)
|
|
|
184
276
|
```typescript
|
|
185
277
|
import { MaxPriorityQueue } from 'data-structure-typed';
|
|
186
278
|
|
|
187
|
-
const pq = new MaxPriorityQueue<Task>(
|
|
279
|
+
const pq = new MaxPriorityQueue<Task>([], {
|
|
280
|
+
comparator: (a, b) => b.priority - a.priority
|
|
281
|
+
});
|
|
188
282
|
pq.add({ id: 1, priority: 5 }); // Add - O(log n)
|
|
189
283
|
const task = pq.poll(); // Remove highest - O(log n)
|
|
190
284
|
const size = pq.size; // Current size
|
|
@@ -266,7 +360,7 @@ heap.peek(); // Highest priority element
|
|
|
266
360
|
heap.size; // Current size
|
|
267
361
|
|
|
268
362
|
// Trie
|
|
269
|
-
trie.
|
|
363
|
+
trie.has('hello'); // true
|
|
270
364
|
trie.hasPrefix('hel'); // true
|
|
271
365
|
|
|
272
366
|
// Graph
|
|
@@ -296,6 +390,12 @@ graph.deleteVertex('A'); // Remove vertex
|
|
|
296
390
|
// All structures support:
|
|
297
391
|
structure.clear(); // Remove all elements
|
|
298
392
|
structure.delete(key); // Remove specific
|
|
393
|
+
|
|
394
|
+
// Conditional delete (BST-family and Deque)
|
|
395
|
+
tree.deleteWhere(node => node.key < 10); // Delete all matching
|
|
396
|
+
tree.deleteWhere(node => node.key < 10, true); // Delete first match only
|
|
397
|
+
tree.deleteWhere(new Range(5, 15)); // Delete by range
|
|
398
|
+
deque.deleteWhere((val, idx) => val > 100); // Deque predicate delete
|
|
299
399
|
```
|
|
300
400
|
|
|
301
401
|
---
|
|
@@ -328,12 +428,33 @@ structure.size; // Element count
|
|
|
328
428
|
structure.isEmpty(); // Check empty
|
|
329
429
|
```
|
|
330
430
|
|
|
431
|
+
### Raw Data Mapping
|
|
432
|
+
|
|
433
|
+
Pass raw objects directly — no `.map()` pre-processing needed:
|
|
434
|
+
|
|
435
|
+
```typescript
|
|
436
|
+
// toElementFn — extract a field, store only that (Heap, Queue, Stack, LinkedList, Trie)
|
|
437
|
+
const heap = new MinHeap<number, User>(users, {
|
|
438
|
+
toElementFn: u => u.age
|
|
439
|
+
});
|
|
440
|
+
|
|
441
|
+
// toEntryFn — split into key-value pairs (TreeMap, HashMap, SkipList)
|
|
442
|
+
const map = new TreeMap<number, User, User>(users, {
|
|
443
|
+
toEntryFn: u => [u.id, u]
|
|
444
|
+
});
|
|
445
|
+
|
|
446
|
+
// comparator — store full objects, sort by a field (all sorted structures)
|
|
447
|
+
const set = new TreeSet<User>(users, {
|
|
448
|
+
comparator: (a, b) => a.id - b.id
|
|
449
|
+
});
|
|
450
|
+
```
|
|
451
|
+
|
|
331
452
|
### Structure-Specific Methods
|
|
332
453
|
|
|
333
454
|
#### Trees
|
|
334
455
|
|
|
335
456
|
```typescript
|
|
336
|
-
tree.height; // Tree height
|
|
457
|
+
tree.height; // Tree height (getter)
|
|
337
458
|
tree.isAVLBalanced(); // Balance check
|
|
338
459
|
tree.getNode(key); // Get node object
|
|
339
460
|
tree.getHeight(key); // Node height
|
|
@@ -344,10 +465,10 @@ tree.getRightMost(); // Rightmost node
|
|
|
344
465
|
#### Deque
|
|
345
466
|
|
|
346
467
|
```typescript
|
|
347
|
-
deque.
|
|
348
|
-
deque.
|
|
349
|
-
deque.
|
|
350
|
-
deque.
|
|
468
|
+
deque.first; // View front (getter)
|
|
469
|
+
deque.last; // View back (getter)
|
|
470
|
+
deque.shift(); // Remove front - O(1)
|
|
471
|
+
deque.pop(); // Remove back - O(1)
|
|
351
472
|
```
|
|
352
473
|
|
|
353
474
|
#### Graph
|
|
@@ -463,7 +584,7 @@ const sorted = [...new RedBlackTree(data).keys()]; // Instant sort!
|
|
|
463
584
|
|
|
464
585
|
---
|
|
465
586
|
|
|
466
|
-
## SkipList
|
|
587
|
+
## SkipList
|
|
467
588
|
|
|
468
589
|
Probabilistic sorted containers. Interchangeable with `TreeMap`/`TreeSet`.
|
|
469
590
|
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
---
|
|
2
2
|
sidebar_label: "PERFORMANCE"
|
|
3
3
|
description: "Benchmarks comparing data-structure-typed vs native Arrays, Maps, and C++ implementations. Includes methodology."
|
|
4
|
+
title: "Performance Benchmarks"
|
|
5
|
+
keywords: [typescript data structures performance, red black tree benchmark, heap benchmark, priority queue performance, javascript vs cpp]
|
|
4
6
|
---
|
|
5
7
|
|
|
6
8
|
# PERFORMANCE
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
description: "Get started with data-structure-typed in 30 seconds. Create trees, queues, and maps with a familiar JavaScript API."
|
|
3
|
+
title: "Quick Start — Get Running in 30 Seconds"
|
|
4
|
+
sidebar_label: "QUICK START"keywords: [data-structure-typed tutorial, typescript data structures getting started, treemap example, heap example]
|
|
3
5
|
---
|
|
4
6
|
|
|
5
7
|
# Quick Start
|
|
@@ -32,6 +34,35 @@ leaderboard.set(95, 'Bob');
|
|
|
32
34
|
const scores90to100 = leaderboard.rangeSearch([90, 100]);
|
|
33
35
|
```
|
|
34
36
|
|
|
37
|
+
## Order-Statistic Tree (Rank Queries)
|
|
38
|
+
|
|
39
|
+
```typescript
|
|
40
|
+
import { RedBlackTree } from 'data-structure-typed';
|
|
41
|
+
|
|
42
|
+
// Enable order-statistic for O(log n) rank operations
|
|
43
|
+
const tree = new RedBlackTree<number, string>([
|
|
44
|
+
[100, 'Alice'],
|
|
45
|
+
[85, 'Bob'],
|
|
46
|
+
[92, 'Charlie'],
|
|
47
|
+
[78, 'Diana'],
|
|
48
|
+
[95, 'Eve']
|
|
49
|
+
], { comparator: (a, b) => b - a, enableOrderStatistic: true });
|
|
50
|
+
|
|
51
|
+
// select(k) — find k-th element (0-indexed)
|
|
52
|
+
console.log(tree.getByRank(0)); // 100 (1st in tree order)
|
|
53
|
+
console.log(tree.getByRank(2)); // 92 (3rd in tree order)
|
|
54
|
+
|
|
55
|
+
// rank(key) — how many elements before this key?
|
|
56
|
+
console.log(tree.getRank(92)); // 2 (2 elements before 92 in tree order)
|
|
57
|
+
|
|
58
|
+
// rangeByRank(start, end) — pagination
|
|
59
|
+
console.log(tree.rangeByRank(0, 2)); // [100, 95, 92] — top 3
|
|
60
|
+
|
|
61
|
+
// Inverse property: getByRank(getRank(key)) === key
|
|
62
|
+
const k = tree.getRank(85);
|
|
63
|
+
console.log(tree.getByRank(k)); // 85
|
|
64
|
+
```
|
|
65
|
+
|
|
35
66
|
## Task Queue (Scheduling)
|
|
36
67
|
|
|
37
68
|
```typescript
|