data-structure-typed 2.5.2 → 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.
Files changed (156) hide show
  1. package/CHANGELOG.md +3 -1
  2. package/MIGRATION.md +169 -0
  3. package/README.md +60 -6
  4. package/README_CN.md +551 -143
  5. package/SPECIFICATION.md +20 -14
  6. package/SPECIFICATION.zh-CN.md +20 -14
  7. package/dist/cjs/binary-tree.cjs +2417 -132
  8. package/dist/cjs/graph.cjs +248 -14
  9. package/dist/cjs/hash.cjs +62 -7
  10. package/dist/cjs/heap.cjs +103 -16
  11. package/dist/cjs/index.cjs +3046 -124
  12. package/dist/cjs/linked-list.cjs +219 -0
  13. package/dist/cjs/matrix.cjs +32 -0
  14. package/dist/cjs/priority-queue.cjs +101 -14
  15. package/dist/cjs/queue.cjs +215 -0
  16. package/dist/cjs/stack.cjs +44 -4
  17. package/dist/cjs/trie.cjs +44 -0
  18. package/dist/cjs-legacy/binary-tree.cjs +2406 -123
  19. package/dist/cjs-legacy/graph.cjs +248 -14
  20. package/dist/cjs-legacy/hash.cjs +62 -7
  21. package/dist/cjs-legacy/heap.cjs +103 -16
  22. package/dist/cjs-legacy/index.cjs +3105 -185
  23. package/dist/cjs-legacy/linked-list.cjs +219 -0
  24. package/dist/cjs-legacy/matrix.cjs +32 -0
  25. package/dist/cjs-legacy/priority-queue.cjs +101 -14
  26. package/dist/cjs-legacy/queue.cjs +215 -0
  27. package/dist/cjs-legacy/stack.cjs +44 -4
  28. package/dist/cjs-legacy/trie.cjs +44 -0
  29. package/dist/esm/binary-tree.mjs +2417 -132
  30. package/dist/esm/graph.mjs +248 -14
  31. package/dist/esm/hash.mjs +62 -7
  32. package/dist/esm/heap.mjs +103 -16
  33. package/dist/esm/index.mjs +3046 -124
  34. package/dist/esm/linked-list.mjs +219 -0
  35. package/dist/esm/matrix.mjs +32 -0
  36. package/dist/esm/priority-queue.mjs +101 -14
  37. package/dist/esm/queue.mjs +215 -0
  38. package/dist/esm/stack.mjs +44 -4
  39. package/dist/esm/trie.mjs +44 -0
  40. package/dist/esm-legacy/binary-tree.mjs +2406 -123
  41. package/dist/esm-legacy/graph.mjs +248 -14
  42. package/dist/esm-legacy/hash.mjs +62 -7
  43. package/dist/esm-legacy/heap.mjs +103 -16
  44. package/dist/esm-legacy/index.mjs +3105 -185
  45. package/dist/esm-legacy/linked-list.mjs +219 -0
  46. package/dist/esm-legacy/matrix.mjs +32 -0
  47. package/dist/esm-legacy/priority-queue.mjs +101 -14
  48. package/dist/esm-legacy/queue.mjs +215 -0
  49. package/dist/esm-legacy/stack.mjs +44 -4
  50. package/dist/esm-legacy/trie.mjs +44 -0
  51. package/dist/types/data-structures/binary-tree/avl-tree.d.ts +50 -2
  52. package/dist/types/data-structures/binary-tree/binary-indexed-tree.d.ts +56 -0
  53. package/dist/types/data-structures/binary-tree/binary-tree.d.ts +116 -15
  54. package/dist/types/data-structures/binary-tree/bst.d.ts +99 -3
  55. package/dist/types/data-structures/binary-tree/red-black-tree.d.ts +79 -8
  56. package/dist/types/data-structures/binary-tree/segment-tree.d.ts +24 -0
  57. package/dist/types/data-structures/binary-tree/tree-map.d.ts +520 -1
  58. package/dist/types/data-structures/binary-tree/tree-multi-map.d.ts +489 -1
  59. package/dist/types/data-structures/binary-tree/tree-multi-set.d.ts +393 -1
  60. package/dist/types/data-structures/binary-tree/tree-set.d.ts +500 -1
  61. package/dist/types/data-structures/graph/directed-graph.d.ts +40 -0
  62. package/dist/types/data-structures/graph/undirected-graph.d.ts +36 -0
  63. package/dist/types/data-structures/hash/hash-map.d.ts +51 -6
  64. package/dist/types/data-structures/heap/heap.d.ts +98 -12
  65. package/dist/types/data-structures/linked-list/doubly-linked-list.d.ts +75 -0
  66. package/dist/types/data-structures/linked-list/singly-linked-list.d.ts +61 -1
  67. package/dist/types/data-structures/linked-list/skip-linked-list.d.ts +72 -0
  68. package/dist/types/data-structures/matrix/matrix.d.ts +32 -0
  69. package/dist/types/data-structures/queue/deque.d.ts +82 -0
  70. package/dist/types/data-structures/queue/queue.d.ts +61 -0
  71. package/dist/types/data-structures/stack/stack.d.ts +42 -2
  72. package/dist/types/data-structures/trie/trie.d.ts +48 -0
  73. package/dist/types/interfaces/binary-tree.d.ts +2 -3
  74. package/dist/umd/data-structure-typed.js +3105 -185
  75. package/dist/umd/data-structure-typed.min.js +4 -4
  76. package/docs-site-docusaurus/docs/api/classes/AVLTree.md +188 -200
  77. package/docs-site-docusaurus/docs/api/classes/AVLTreeNode.md +11 -11
  78. package/docs-site-docusaurus/docs/api/classes/AbstractGraph.md +62 -62
  79. package/docs-site-docusaurus/docs/api/classes/BST.md +183 -195
  80. package/docs-site-docusaurus/docs/api/classes/BSTNode.md +13 -13
  81. package/docs-site-docusaurus/docs/api/classes/BinaryIndexedTree.md +15 -15
  82. package/docs-site-docusaurus/docs/api/classes/BinaryTree.md +143 -155
  83. package/docs-site-docusaurus/docs/api/classes/BinaryTreeNode.md +13 -13
  84. package/docs-site-docusaurus/docs/api/classes/Deque.md +99 -85
  85. package/docs-site-docusaurus/docs/api/classes/DirectedGraph.md +73 -73
  86. package/docs-site-docusaurus/docs/api/classes/DoublyLinkedList.md +100 -70
  87. package/docs-site-docusaurus/docs/api/classes/DoublyLinkedListNode.md +8 -8
  88. package/docs-site-docusaurus/docs/api/classes/FibonacciHeap.md +12 -12
  89. package/docs-site-docusaurus/docs/api/classes/FibonacciHeapNode.md +1 -1
  90. package/docs-site-docusaurus/docs/api/classes/HashMap.md +38 -38
  91. package/docs-site-docusaurus/docs/api/classes/Heap.md +96 -85
  92. package/docs-site-docusaurus/docs/api/classes/IterableElementBase.md +25 -25
  93. package/docs-site-docusaurus/docs/api/classes/IterableEntryBase.md +23 -23
  94. package/docs-site-docusaurus/docs/api/classes/LinearBase.md +48 -48
  95. package/docs-site-docusaurus/docs/api/classes/LinearLinkedBase.md +52 -52
  96. package/docs-site-docusaurus/docs/api/classes/LinkedHashMap.md +42 -42
  97. package/docs-site-docusaurus/docs/api/classes/LinkedListNode.md +6 -6
  98. package/docs-site-docusaurus/docs/api/classes/LinkedListQueue.md +74 -74
  99. package/docs-site-docusaurus/docs/api/classes/MapGraph.md +73 -73
  100. package/docs-site-docusaurus/docs/api/classes/Matrix.md +31 -31
  101. package/docs-site-docusaurus/docs/api/classes/MaxHeap.md +104 -89
  102. package/docs-site-docusaurus/docs/api/classes/MaxPriorityQueue.md +104 -89
  103. package/docs-site-docusaurus/docs/api/classes/MinHeap.md +104 -89
  104. package/docs-site-docusaurus/docs/api/classes/MinPriorityQueue.md +104 -89
  105. package/docs-site-docusaurus/docs/api/classes/Navigator.md +5 -5
  106. package/docs-site-docusaurus/docs/api/classes/PriorityQueue.md +103 -88
  107. package/docs-site-docusaurus/docs/api/classes/Queue.md +111 -59
  108. package/docs-site-docusaurus/docs/api/classes/RedBlackTree.md +200 -212
  109. package/docs-site-docusaurus/docs/api/classes/SegmentTree.md +10 -10
  110. package/docs-site-docusaurus/docs/api/classes/SinglyLinkedList.md +75 -75
  111. package/docs-site-docusaurus/docs/api/classes/SinglyLinkedListNode.md +6 -6
  112. package/docs-site-docusaurus/docs/api/classes/SkipList.md +37 -37
  113. package/docs-site-docusaurus/docs/api/classes/Stack.md +42 -42
  114. package/docs-site-docusaurus/docs/api/classes/TreeMap.md +107 -36
  115. package/docs-site-docusaurus/docs/api/classes/TreeMultiMap.md +43 -43
  116. package/docs-site-docusaurus/docs/api/classes/TreeSet.md +106 -35
  117. package/docs-site-docusaurus/docs/api/classes/Trie.md +43 -43
  118. package/docs-site-docusaurus/docs/api/classes/TrieNode.md +8 -8
  119. package/docs-site-docusaurus/docs/api/classes/UndirectedGraph.md +72 -72
  120. package/docs-site-docusaurus/docs/guide/architecture.md +75 -7
  121. package/docs-site-docusaurus/docs/guide/concepts.md +53 -34
  122. package/docs-site-docusaurus/docs/guide/faq.md +53 -0
  123. package/docs-site-docusaurus/docs/guide/guides.md +8 -9
  124. package/docs-site-docusaurus/docs/guide/integrations.md +74 -177
  125. package/docs-site-docusaurus/docs/guide/overview.md +131 -17
  126. package/docs-site-docusaurus/src/pages/index.tsx +4 -0
  127. package/docs-site-docusaurus/typedoc.json +1 -0
  128. package/package.json +7 -6
  129. package/src/data-structures/binary-tree/avl-tree.ts +52 -5
  130. package/src/data-structures/binary-tree/binary-indexed-tree.ts +56 -0
  131. package/src/data-structures/binary-tree/binary-tree.ts +167 -81
  132. package/src/data-structures/binary-tree/bst.ts +101 -7
  133. package/src/data-structures/binary-tree/red-black-tree.ts +82 -15
  134. package/src/data-structures/binary-tree/segment-tree.ts +24 -0
  135. package/src/data-structures/binary-tree/tree-map.ts +540 -3
  136. package/src/data-structures/binary-tree/tree-multi-map.ts +490 -2
  137. package/src/data-structures/binary-tree/tree-multi-set.ts +393 -1
  138. package/src/data-structures/binary-tree/tree-set.ts +520 -3
  139. package/src/data-structures/graph/directed-graph.ts +41 -1
  140. package/src/data-structures/graph/undirected-graph.ts +37 -1
  141. package/src/data-structures/hash/hash-map.ts +67 -12
  142. package/src/data-structures/heap/heap.ts +107 -19
  143. package/src/data-structures/linked-list/doubly-linked-list.ts +88 -0
  144. package/src/data-structures/linked-list/singly-linked-list.ts +61 -1
  145. package/src/data-structures/linked-list/skip-linked-list.ts +72 -0
  146. package/src/data-structures/matrix/matrix.ts +32 -0
  147. package/src/data-structures/queue/deque.ts +85 -0
  148. package/src/data-structures/queue/queue.ts +73 -0
  149. package/src/data-structures/stack/stack.ts +45 -5
  150. package/src/data-structures/trie/trie.ts +48 -0
  151. package/src/interfaces/binary-tree.ts +1 -9
  152. package/.vitepress/cache/deps_temp_51f5f1b0/chunk-7OIKW5WK.js +0 -12984
  153. package/.vitepress/cache/deps_temp_51f5f1b0/package.json +0 -3
  154. package/.vitepress/cache/deps_temp_51f5f1b0/vitepress___@vue_devtools-api.js +0 -4505
  155. package/.vitepress/cache/deps_temp_51f5f1b0/vitepress___@vueuse_core.js +0 -9731
  156. package/.vitepress/cache/deps_temp_51f5f1b0/vue.js +0 -347
@@ -2,14 +2,13 @@
2
2
  sidebar_label: "INTEGRATIONS"
3
3
  description: "Integrate data-structure-typed with React, Express, NestJS, and other frameworks. Production-ready patterns."
4
4
  title: "Framework Integrations — React, Express, NestJS"
5
- keywords: [data-structure-typed react, typescript data structures express, nestjs data structures, production patterns]
5
+ keywords: ["data-structure-typed react", "typescript data structures express", "nestjs data structures", "production patterns"]
6
6
  ---
7
-
8
7
  # INTEGRATIONS
9
8
 
10
9
  How to use data-structure-typed with React, Express, Nest.js, and other frameworks.
11
10
 
12
- **[Back to README](/.md) • [Code Examples](/guide/guides.md) • [Performance](/guide/performance.md)**
11
+ **[Back to README](/docs/guide/quick-start) • [Code Examples](/guide/guides.md) • [Performance](/guide/performance.md)**
13
12
 
14
13
  ---
15
14
 
@@ -291,6 +290,8 @@ app.get('/api/data', (req, res) => {
291
290
 
292
291
  ### Use Case: Product Price Index Service
293
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
+
294
295
  ```typescript
295
296
  import {
296
297
  BadRequestException,
@@ -309,7 +310,6 @@ export interface Product {
309
310
  lastUpdated?: Date;
310
311
  }
311
312
 
312
- /** KEY INSIGHT: Use compound keys to solve the problem of "multiple products at the same price" */
313
313
  interface CompositeKey {
314
314
  price: number;
315
315
  productId: string;
@@ -328,13 +328,8 @@ export type TierName = 'budget' | 'mid-range' | 'premium';
328
328
  * Point Lookup | O(1) | O(1) | O(1)
329
329
  * Insert/Update | O(log n) | O(n) | O(log n)
330
330
  * Sort by Price | O(n) | O(n log n)| O(n log n)
331
- * Multiple at Price | Supported | | Complex
332
- *
333
- * Advantages:
334
- * - O(1) idToKeyMap lookup + O(log n) tree operations
335
- * - Automatic ordering without post-sort
336
- * - Efficient range queries for pricing tiers
337
- * - 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)
338
333
  */
339
334
  @Injectable()
340
335
  export class ProductPriceIndexService {
@@ -348,228 +343,130 @@ export class ProductPriceIndexService {
348
343
  if (priceCmp !== 0) return priceCmp;
349
344
  return a.productId.localeCompare(b.productId);
350
345
  },
346
+ enableOrderStatistic: true, // Enables getRank/getByRank/rangeByRank
351
347
  });
352
348
  this.idToKeyMap = new Map();
353
349
  }
354
350
 
355
- /** Time Complexity: O(log n) */
351
+ /** O(log n) */
356
352
  addProduct(product: Product): Product {
357
353
  if (this.idToKeyMap.has(product.id))
358
354
  throw new BadRequestException(`Product ${product.id} already exists`);
359
355
 
360
356
  product.lastUpdated = new Date();
361
-
362
- const key: CompositeKey = {
363
- price: product.price,
364
- productId: product.id,
365
- };
366
-
367
- this.priceIndex.add(key, product);
357
+ const key: CompositeKey = { price: product.price, productId: product.id };
358
+ this.priceIndex.set(key, product);
368
359
  this.idToKeyMap.set(product.id, key);
369
-
370
360
  return product;
371
361
  }
372
362
 
373
- /** Time Complexity: O(log n) */
374
- updateProduct(productId: string, updates: Partial<Product>): Product {
375
- const oldKey = this.idToKeyMap.get(productId);
376
- if (oldKey === undefined)
377
- throw new NotFoundException(`Product ${productId} not found`);
378
-
379
- const existing = this.priceIndex.get(oldKey);
380
- if (!existing)
381
- throw new NotFoundException(`Product ${productId} not found`);
382
-
383
- const updated: Product = {
384
- ...existing,
385
- ...updates,
386
- id: existing.id,
387
- lastUpdated: new Date(),
388
- };
389
-
390
- const newPrice = updates.price ?? existing.price;
391
-
392
- this.priceIndex.delete(oldKey);
393
- const currentKey: CompositeKey = {
394
- price: newPrice,
395
- productId,
396
- };
397
- this.priceIndex.set(currentKey, updated);
398
- this.idToKeyMap.set(productId, currentKey);
399
-
400
- return updated;
401
- }
402
-
403
- /** Time Complexity: O(1) */
363
+ /** O(1) — HashMap lookup */
404
364
  getProductById(productId: string): Product {
405
365
  const key = this.idToKeyMap.get(productId);
406
-
407
366
  if (key === undefined)
408
367
  throw new NotFoundException(`Product ${productId} not found`);
409
-
410
368
  return this.priceIndex.get(key)!;
411
369
  }
412
370
 
413
- /** Time Complexity: O(log n + k) */
371
+ /** O(log n + k) — directly returns values, no secondary lookup */
414
372
  getProductsByPriceRange(minPrice: number, maxPrice: number): Product[] {
415
373
  const range = new Range(
416
374
  { price: minPrice, productId: '' },
417
375
  { price: maxPrice, productId: '\uffff' },
418
- true, // includeLow
419
- true, // includeHigh
376
+ true,
377
+ true,
420
378
  );
421
-
422
- const keys = this.priceIndex.rangeSearch(range, (n) => n.key);
423
- return keys.map((key) => this.priceIndex.get(key)!);
379
+ return this.priceIndex.rangeSearch(range, (n) => n.value!);
424
380
  }
425
381
 
426
- /** Time Complexity: O(log n) */
382
+ /** O(log n) — NavigableMap floor() */
427
383
  getHighestPricedProductWithinBudget(maxBudget: number): Product | null {
428
- const key: CompositeKey = {
429
- price: maxBudget,
430
- productId: '\uffff',
431
- };
384
+ const key: CompositeKey = { price: maxBudget, productId: '\uffff' };
432
385
  const floorKey = this.priceIndex.floor(key);
433
386
  return floorKey ? this.priceIndex.get(floorKey)! : null;
434
387
  }
435
388
 
436
- /** Time O(log n) */
437
- getCheapestProductAbovePrice(minPrice: number): Product | null {
438
- const key: CompositeKey = {
439
- price: minPrice,
440
- productId: '\uffff',
441
- };
442
- const higherKey = this.priceIndex.higher(key);
443
- return higherKey ? this.priceIndex.get(higherKey)! : null;
444
- }
445
-
446
- /** Time Complexity: O(log n + k) */
447
- getProductsByTier(tierName: TierName): Product[] {
448
- const tiers = {
449
- budget: [0, 50],
450
- 'mid-range': [50, 200],
451
- premium: [200, Infinity],
452
- };
453
-
454
- const [min, max] = tiers[tierName];
455
- return this.getProductsByPriceRange(min, max);
456
- }
457
-
458
- /** Time Complexity: O(log n + k + m) */
459
- getProductsByPriceAndCategory(
460
- minPrice: number,
461
- maxPrice: number,
462
- category: string,
463
- ): Product[] {
464
- const priceRangeProducts = this.getProductsByPriceRange(minPrice, maxPrice);
465
- return priceRangeProducts.filter(
466
- (p) => p.category.toLowerCase() === category.toLowerCase(),
467
- );
468
- }
469
-
470
- /** Time Complexity: O((log n + k) * log n) */
471
- applyDiscountToRange(
472
- minPrice: number,
473
- maxPrice: number,
474
- discountPercent: number,
475
- ): Product[] {
476
- const products = this.getProductsByPriceRange(minPrice, maxPrice);
477
- const updated: Product[] = [];
478
-
479
- for (const product of products) {
480
- const newPrice = product.price * (1 - discountPercent / 100);
481
- const updatedProduct = this.updateProduct(product.id, {
482
- price: newPrice,
483
- });
484
- updated.push(updatedProduct);
485
- }
486
-
487
- return updated;
389
+ /** O(n) — iterator protocol, one-liner */
390
+ getAllProductsSortedByPrice(): Product[] {
391
+ return [...this.priceIndex.values()];
488
392
  }
489
393
 
490
- /** Time Complexity: O(log n) */
491
- deleteProduct(productId: string): void {
492
- const key = this.idToKeyMap.get(productId);
493
-
494
- if (key === undefined)
495
- throw new NotFoundException(`Product ${productId} not found`);
496
-
497
- this.priceIndex.delete(key);
498
- this.idToKeyMap.delete(productId);
499
- }
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 };
500
401
 
501
- /** Time Complexity: O(n) */
502
- getStatistics(): {
503
- totalProducts: number;
504
- priceRange: { min: number; max: number };
505
- averagePrice: number;
506
- totalValue: number;
507
- } {
508
- if (this.idToKeyMap.size === 0) {
509
- return {
510
- totalProducts: 0,
511
- priceRange: { min: 0, max: 0 },
512
- averagePrice: 0,
513
- totalValue: 0,
514
- };
515
- }
402
+ const minKey = this.priceIndex.getLeftMost();
403
+ const maxKey = this.priceIndex.getRightMost();
516
404
 
517
- let minPrice = Infinity;
518
- let maxPrice = -Infinity;
519
405
  let totalValue = 0;
520
406
  let totalProducts = 0;
521
-
522
- let entry = this.priceIndex.getLeftMost((node) => node);
523
-
524
- while (entry) {
525
- const product = this.priceIndex.get(entry.key);
526
- if (product) {
527
- minPrice = Math.min(minPrice, product.price);
528
- maxPrice = Math.max(maxPrice, product.price);
529
- totalValue += product.price * product.quantity;
530
- totalProducts += product.quantity;
531
- }
532
-
533
- 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;
534
410
  }
535
411
 
536
412
  return {
537
- totalProducts: totalProducts,
538
- priceRange: { min: minPrice, max: maxPrice },
413
+ totalProducts,
414
+ priceRange: { min: minKey?.price ?? 0, max: maxKey?.price ?? 0 },
539
415
  averagePrice: totalValue / totalProducts,
540
416
  totalValue,
541
417
  };
542
418
  }
543
419
 
544
- /** Time Complexity: O(n) */
545
- getAllProductsSortedByPrice(): Product[] {
546
- const products: Product[] = [];
547
- let curNode = this.priceIndex.getLeftMost((node) => node);
420
+ // ── Order-Statistic API (rank-based queries) ──────────────────────
548
421
 
549
- while (curNode) {
550
- if (curNode.key) products.push(this.priceIndex.get(curNode.key)!);
551
- curNode = this.priceIndex.higher(curNode.key, (node) => node);
552
- }
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
+ }
553
430
 
554
- return products;
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;
555
436
  }
556
437
 
557
- /** O(1) */
558
- getProductCount(): number {
559
- return this.idToKeyMap.size;
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;
560
443
  }
561
444
 
562
- /** O(1) */
563
- hasProduct(productId: string): boolean {
564
- return this.idToKeyMap.has(productId);
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)!);
565
450
  }
566
451
 
567
- /** O(n) */
568
- getAllProductIds(): string[] {
569
- return [...this.idToKeyMap.keys()];
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();
570
460
  }
571
- }
572
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
+ }
573
470
  ```
574
471
 
575
472
  ### Use Case: Task Queue Controller
@@ -2,14 +2,13 @@
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
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]
5
+ keywords: ["typescript data structures overview", "red black tree", "heap", "priority queue", "trie", "graph", "deque", "treemap", "treeset"]
6
6
  ---
7
-
8
7
  # OVERVIEW
9
8
 
10
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/)**.
11
10
 
12
- **[Back to README](/.md) • [API Docs](https://data-structure-typed-docs.vercel.app/) • [Real-World Examples](/guide/guides.md) • [Performance](/guide/performance.md)**
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)**
13
12
 
14
13
  ---
15
14
 
@@ -57,7 +56,7 @@ A quick-reference guide to all structures, common operations, and usage patterns
57
56
  import { Stack } from 'data-structure-typed';
58
57
 
59
58
  const stack = new Stack<number>([1, 2]);
60
- stack.push(3); // add to bottom
59
+ stack.push(3); // add to top
61
60
  const top = stack.pop(); // Remove from top - O(1)
62
61
  const peek = stack.peek(); // View top
63
62
  stack.print(); // [1, 2]
@@ -149,11 +148,6 @@ rbTree.print()
149
148
  // / \
150
149
  // 1 4
151
150
 
152
- // Order-Statistic mode — O(log n) rank queries
153
- const ost = new RedBlackTree<number, string>([[1, 'A'], [2, 'B'], [3, 'C']], { enableOrderStatistic: true });
154
- ost.getByRank(0); // 1 (smallest key)
155
- ost.getRank(2); // 1 (one element before key 2)
156
- ost.rangeByRank(0, 1); // [1, 2] (first two elements)
157
151
  ```
158
152
 
159
153
  #### AVL Tree
@@ -173,6 +167,97 @@ avl.print()
173
167
  // 4 9
174
168
  ```
175
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
+
176
261
  ### Heap & Priority Queue
177
262
 
178
263
  #### Heap
@@ -191,7 +276,9 @@ const peek = minHeap.peek(); // View minimum - O(1)
191
276
  ```typescript
192
277
  import { MaxPriorityQueue } from 'data-structure-typed';
193
278
 
194
- const pq = new MaxPriorityQueue<Task>();
279
+ const pq = new MaxPriorityQueue<Task>([], {
280
+ comparator: (a, b) => b.priority - a.priority
281
+ });
195
282
  pq.add({ id: 1, priority: 5 }); // Add - O(log n)
196
283
  const task = pq.poll(); // Remove highest - O(log n)
197
284
  const size = pq.size; // Current size
@@ -273,7 +360,7 @@ heap.peek(); // Highest priority element
273
360
  heap.size; // Current size
274
361
 
275
362
  // Trie
276
- trie.getWords('hello'); // true
363
+ trie.has('hello'); // true
277
364
  trie.hasPrefix('hel'); // true
278
365
 
279
366
  // Graph
@@ -303,6 +390,12 @@ graph.deleteVertex('A'); // Remove vertex
303
390
  // All structures support:
304
391
  structure.clear(); // Remove all elements
305
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
306
399
  ```
307
400
 
308
401
  ---
@@ -335,12 +428,33 @@ structure.size; // Element count
335
428
  structure.isEmpty(); // Check empty
336
429
  ```
337
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
+
338
452
  ### Structure-Specific Methods
339
453
 
340
454
  #### Trees
341
455
 
342
456
  ```typescript
343
- tree.height; // Tree height
457
+ tree.height; // Tree height (getter)
344
458
  tree.isAVLBalanced(); // Balance check
345
459
  tree.getNode(key); // Get node object
346
460
  tree.getHeight(key); // Node height
@@ -351,10 +465,10 @@ tree.getRightMost(); // Rightmost node
351
465
  #### Deque
352
466
 
353
467
  ```typescript
354
- deque.peekFirst(); // View front
355
- deque.peekLast(); // View back
356
- deque.pollFirst(); // Remove front - O(1)
357
- deque.pollLast(); // Remove back - O(1)
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)
358
472
  ```
359
473
 
360
474
  #### Graph
@@ -470,7 +584,7 @@ const sorted = [...new RedBlackTree(data).keys()]; // Instant sort!
470
584
 
471
585
  ---
472
586
 
473
- ## SkipList & SkipListSet
587
+ ## SkipList
474
588
 
475
589
  Probabilistic sorted containers. Interchangeable with `TreeMap`/`TreeSet`.
476
590
 
@@ -42,6 +42,10 @@ const features = [
42
42
  title: '📦 Zero Dependencies',
43
43
  description: 'Pure TypeScript. No runtime dependencies. Tree-shakeable with subpath exports — bundle only what you use.',
44
44
  },
45
+ {
46
+ title: '🔄 Raw Data In, Structure Out',
47
+ description: 'Pass raw objects directly with toEntryFn, toElementFn, or comparator. No .map() pre-processing needed — unique to this library in JS/TS.',
48
+ },
45
49
  {
46
50
  title: '✅ Battle-Tested',
47
51
  description: '2600+ tests, 99%+ coverage. CLRS-correct Red-Black Tree, ACL-style Segment Tree. Production-ready.',
@@ -1,6 +1,7 @@
1
1
  {
2
2
  "entryPoints": ["../src/data-structures"],
3
3
  "tsconfig": "../tsconfig.json",
4
+ "gitRevision": "main",
4
5
  "out": "./docs/api",
5
6
  "plugin": ["typedoc-plugin-markdown", "../scripts/typedoc-plugin-example-rewrite.js"],
6
7
  "cleanOutputDir": true,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "data-structure-typed",
3
- "version": "2.5.2",
3
+ "version": "2.5.3",
4
4
  "description": "Production-ready TypeScript data structures: Heap, Deque, Trie, Graph, Red-Black Tree, TreeMap, TreeSet, and more. Zero dependencies, type-safe, with getRank/getByRank/rangeByRank support.",
5
5
  "browser": "dist/umd/data-structure-typed.min.js",
6
6
  "umd:main": "dist/umd/data-structure-typed.min.js",
@@ -154,6 +154,7 @@
154
154
  "format:test": "prettier --write 'test/**/*.{js,ts}'",
155
155
  "inspect": "npm run build && npm run check && npm run lint",
156
156
  "ci": "env && git fetch --tags && npm run update:subs && npm run inspect && npm run test:coverage && npm run changelog",
157
+ "docs:sync": "node scripts/sync-docs-to-site.mjs",
157
158
  "docs:api": "npm run gen:examples && npm run build:typedoc-plugin && cd docs-site-docusaurus && npx typedoc --options typedoc.json && node sort-protected.mjs",
158
159
  "docs:dev": "cd docs-site-docusaurus && npm run start",
159
160
  "docs:build": "cd docs-site-docusaurus && rm -rf docs/api && npx typedoc --options typedoc.json && node sort-protected.mjs && npm run build",
@@ -193,11 +194,11 @@
193
194
  "@typescript-eslint/eslint-plugin": "^8.12.1",
194
195
  "@typescript-eslint/parser": "^8.12.1",
195
196
  "auto-changelog": "^2.5.0",
196
- "avl-tree-typed": "^2.5.1",
197
+ "avl-tree-typed": "^2.5.2",
197
198
  "benchmark": "^2.1.4",
198
- "binary-tree-typed": "^2.5.1",
199
- "bst-typed": "^2.5.1",
200
- "data-structure-typed": "^2.5.1",
199
+ "binary-tree-typed": "^2.5.2",
200
+ "bst-typed": "^2.5.2",
201
+ "data-structure-typed": "^2.5.2",
201
202
  "dependency-cruiser": "^16.5.0",
202
203
  "doctoc": "^2.2.1",
203
204
  "eslint": "^9.13.0",
@@ -206,7 +207,7 @@
206
207
  "eslint-import-resolver-typescript": "^3.6.3",
207
208
  "eslint-plugin-import": "^2.31.0",
208
209
  "fast-glob": "^3.3.2",
209
- "heap-typed": "^2.5.1",
210
+ "heap-typed": "^2.5.2",
210
211
  "istanbul-badges-readme": "^1.9.0",
211
212
  "jest": "^29.7.0",
212
213
  "js-sdsl": "^4.4.2",