graph-typed 2.4.4 → 2.5.0

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 (84) hide show
  1. package/dist/cjs/index.cjs +1324 -220
  2. package/dist/cjs/index.cjs.map +1 -1
  3. package/dist/cjs-legacy/index.cjs +1325 -219
  4. package/dist/cjs-legacy/index.cjs.map +1 -1
  5. package/dist/esm/index.mjs +1324 -221
  6. package/dist/esm/index.mjs.map +1 -1
  7. package/dist/esm-legacy/index.mjs +1325 -220
  8. package/dist/esm-legacy/index.mjs.map +1 -1
  9. package/dist/types/common/error.d.ts +23 -0
  10. package/dist/types/common/index.d.ts +1 -0
  11. package/dist/types/data-structures/base/iterable-element-base.d.ts +1 -1
  12. package/dist/types/data-structures/binary-tree/avl-tree.d.ts +128 -51
  13. package/dist/types/data-structures/binary-tree/binary-indexed-tree.d.ts +210 -164
  14. package/dist/types/data-structures/binary-tree/binary-tree.d.ts +439 -78
  15. package/dist/types/data-structures/binary-tree/bst.d.ts +311 -28
  16. package/dist/types/data-structures/binary-tree/red-black-tree.d.ts +217 -31
  17. package/dist/types/data-structures/binary-tree/segment-tree.d.ts +218 -152
  18. package/dist/types/data-structures/binary-tree/tree-map.d.ts +1281 -5
  19. package/dist/types/data-structures/binary-tree/tree-multi-map.d.ts +1087 -201
  20. package/dist/types/data-structures/binary-tree/tree-multi-set.d.ts +858 -65
  21. package/dist/types/data-structures/binary-tree/tree-set.d.ts +1133 -5
  22. package/dist/types/data-structures/graph/abstract-graph.d.ts +44 -0
  23. package/dist/types/data-structures/graph/directed-graph.d.ts +220 -47
  24. package/dist/types/data-structures/graph/map-graph.d.ts +59 -1
  25. package/dist/types/data-structures/graph/undirected-graph.d.ts +218 -59
  26. package/dist/types/data-structures/hash/hash-map.d.ts +230 -77
  27. package/dist/types/data-structures/heap/heap.d.ts +287 -99
  28. package/dist/types/data-structures/heap/max-heap.d.ts +46 -0
  29. package/dist/types/data-structures/heap/min-heap.d.ts +59 -0
  30. package/dist/types/data-structures/linked-list/doubly-linked-list.d.ts +286 -44
  31. package/dist/types/data-structures/linked-list/singly-linked-list.d.ts +278 -65
  32. package/dist/types/data-structures/linked-list/skip-linked-list.d.ts +415 -12
  33. package/dist/types/data-structures/matrix/matrix.d.ts +331 -0
  34. package/dist/types/data-structures/priority-queue/max-priority-queue.d.ts +57 -0
  35. package/dist/types/data-structures/priority-queue/min-priority-queue.d.ts +60 -0
  36. package/dist/types/data-structures/priority-queue/priority-queue.d.ts +60 -0
  37. package/dist/types/data-structures/queue/deque.d.ts +313 -66
  38. package/dist/types/data-structures/queue/queue.d.ts +211 -42
  39. package/dist/types/data-structures/stack/stack.d.ts +174 -32
  40. package/dist/types/data-structures/trie/trie.d.ts +213 -43
  41. package/dist/types/types/data-structures/binary-tree/segment-tree.d.ts +1 -1
  42. package/dist/types/types/data-structures/linked-list/skip-linked-list.d.ts +1 -4
  43. package/dist/types/types/data-structures/queue/deque.d.ts +6 -0
  44. package/dist/umd/graph-typed.js +1323 -217
  45. package/dist/umd/graph-typed.js.map +1 -1
  46. package/dist/umd/graph-typed.min.js +3 -1
  47. package/dist/umd/graph-typed.min.js.map +1 -1
  48. package/package.json +2 -2
  49. package/src/common/error.ts +60 -0
  50. package/src/common/index.ts +2 -0
  51. package/src/data-structures/base/iterable-element-base.ts +2 -2
  52. package/src/data-structures/binary-tree/avl-tree.ts +134 -51
  53. package/src/data-structures/binary-tree/binary-indexed-tree.ts +303 -247
  54. package/src/data-structures/binary-tree/binary-tree.ts +542 -121
  55. package/src/data-structures/binary-tree/bst.ts +346 -37
  56. package/src/data-structures/binary-tree/red-black-tree.ts +309 -96
  57. package/src/data-structures/binary-tree/segment-tree.ts +372 -248
  58. package/src/data-structures/binary-tree/tree-map.ts +1292 -13
  59. package/src/data-structures/binary-tree/tree-multi-map.ts +1098 -215
  60. package/src/data-structures/binary-tree/tree-multi-set.ts +863 -69
  61. package/src/data-structures/binary-tree/tree-set.ts +1143 -15
  62. package/src/data-structures/graph/abstract-graph.ts +106 -1
  63. package/src/data-structures/graph/directed-graph.ts +223 -47
  64. package/src/data-structures/graph/map-graph.ts +59 -1
  65. package/src/data-structures/graph/undirected-graph.ts +299 -59
  66. package/src/data-structures/hash/hash-map.ts +243 -79
  67. package/src/data-structures/heap/heap.ts +291 -102
  68. package/src/data-structures/heap/max-heap.ts +48 -3
  69. package/src/data-structures/heap/min-heap.ts +59 -0
  70. package/src/data-structures/linked-list/doubly-linked-list.ts +286 -44
  71. package/src/data-structures/linked-list/singly-linked-list.ts +278 -65
  72. package/src/data-structures/linked-list/skip-linked-list.ts +689 -90
  73. package/src/data-structures/matrix/matrix.ts +425 -22
  74. package/src/data-structures/priority-queue/max-priority-queue.ts +59 -3
  75. package/src/data-structures/priority-queue/min-priority-queue.ts +60 -0
  76. package/src/data-structures/priority-queue/priority-queue.ts +60 -0
  77. package/src/data-structures/queue/deque.ts +343 -68
  78. package/src/data-structures/queue/queue.ts +211 -42
  79. package/src/data-structures/stack/stack.ts +174 -32
  80. package/src/data-structures/trie/trie.ts +215 -44
  81. package/src/types/data-structures/binary-tree/segment-tree.ts +1 -1
  82. package/src/types/data-structures/linked-list/skip-linked-list.ts +2 -1
  83. package/src/types/data-structures/queue/deque.ts +7 -0
  84. package/src/utils/utils.ts +4 -2
@@ -24,6 +24,55 @@ var arrayRemove = /* @__PURE__ */ __name(function(array, predicate) {
24
24
  return result;
25
25
  }, "arrayRemove");
26
26
 
27
+ // src/common/error.ts
28
+ var ERR = {
29
+ // Range / index
30
+ indexOutOfRange: /* @__PURE__ */ __name((index, min, max, ctx) => `${ctx ? ctx + ": " : ""}Index ${index} is out of range [${min}, ${max}].`, "indexOutOfRange"),
31
+ invalidIndex: /* @__PURE__ */ __name((ctx) => `${ctx ? ctx + ": " : ""}Index must be an integer.`, "invalidIndex"),
32
+ // Type / argument
33
+ invalidArgument: /* @__PURE__ */ __name((reason, ctx) => `${ctx ? ctx + ": " : ""}${reason}`, "invalidArgument"),
34
+ comparatorRequired: /* @__PURE__ */ __name((ctx) => `${ctx ? ctx + ": " : ""}Comparator is required for non-number/non-string/non-Date keys.`, "comparatorRequired"),
35
+ invalidKey: /* @__PURE__ */ __name((reason, ctx) => `${ctx ? ctx + ": " : ""}${reason}`, "invalidKey"),
36
+ notAFunction: /* @__PURE__ */ __name((name, ctx) => `${ctx ? ctx + ": " : ""}${name} must be a function.`, "notAFunction"),
37
+ invalidEntry: /* @__PURE__ */ __name((ctx) => `${ctx ? ctx + ": " : ""}Each entry must be a [key, value] tuple.`, "invalidEntry"),
38
+ invalidNaN: /* @__PURE__ */ __name((ctx) => `${ctx ? ctx + ": " : ""}NaN is not a valid key.`, "invalidNaN"),
39
+ invalidDate: /* @__PURE__ */ __name((ctx) => `${ctx ? ctx + ": " : ""}Invalid Date key.`, "invalidDate"),
40
+ reduceEmpty: /* @__PURE__ */ __name((ctx) => `${ctx ? ctx + ": " : ""}Reduce of empty structure with no initial value.`, "reduceEmpty"),
41
+ callbackReturnType: /* @__PURE__ */ __name((expected, got, ctx) => `${ctx ? ctx + ": " : ""}Callback must return ${expected}; got ${got}.`, "callbackReturnType"),
42
+ // State / operation
43
+ invalidOperation: /* @__PURE__ */ __name((reason, ctx) => `${ctx ? ctx + ": " : ""}${reason}`, "invalidOperation"),
44
+ // Matrix
45
+ matrixDimensionMismatch: /* @__PURE__ */ __name((op) => `Matrix: Dimensions must be compatible for ${op}.`, "matrixDimensionMismatch"),
46
+ matrixSingular: /* @__PURE__ */ __name(() => "Matrix: Singular matrix, inverse does not exist.", "matrixSingular"),
47
+ matrixNotSquare: /* @__PURE__ */ __name(() => "Matrix: Must be square for inversion.", "matrixNotSquare"),
48
+ matrixNotRectangular: /* @__PURE__ */ __name(() => "Matrix: Must be rectangular for transposition.", "matrixNotRectangular"),
49
+ matrixRowMismatch: /* @__PURE__ */ __name((expected, got) => `Matrix: Expected row length ${expected}, but got ${got}.`, "matrixRowMismatch")
50
+ };
51
+
52
+ // src/common/index.ts
53
+ var DFSOperation = /* @__PURE__ */ ((DFSOperation2) => {
54
+ DFSOperation2[DFSOperation2["VISIT"] = 0] = "VISIT";
55
+ DFSOperation2[DFSOperation2["PROCESS"] = 1] = "PROCESS";
56
+ return DFSOperation2;
57
+ })(DFSOperation || {});
58
+ var Range = class {
59
+ constructor(low, high, includeLow = true, includeHigh = true) {
60
+ this.low = low;
61
+ this.high = high;
62
+ this.includeLow = includeLow;
63
+ this.includeHigh = includeHigh;
64
+ }
65
+ static {
66
+ __name(this, "Range");
67
+ }
68
+ // Determine whether a key is within the range
69
+ isInRange(key, comparator) {
70
+ const lowCheck = this.includeLow ? comparator(key, this.low) >= 0 : comparator(key, this.low) > 0;
71
+ const highCheck = this.includeHigh ? comparator(key, this.high) <= 0 : comparator(key, this.high) < 0;
72
+ return lowCheck && highCheck;
73
+ }
74
+ };
75
+
27
76
  // src/data-structures/base/iterable-entry-base.ts
28
77
  var IterableEntryBase = class {
29
78
  static {
@@ -460,10 +509,30 @@ var Heap = class _Heap extends IterableElementBase {
460
509
  return this._elements;
461
510
  }
462
511
  /**
463
- * Get the number of elements.
464
- * @remarks Time O(1), Space O(1)
465
- * @returns Heap size.
466
- */
512
+ * Get the number of elements.
513
+ * @remarks Time O(1), Space O(1)
514
+ * @returns Heap size.
515
+
516
+
517
+
518
+
519
+
520
+
521
+
522
+
523
+
524
+
525
+
526
+ * @example
527
+ * // Track heap capacity
528
+ * const heap = new Heap<number>();
529
+ * console.log(heap.size); // 0;
530
+ * heap.add(10);
531
+ * heap.add(20);
532
+ * console.log(heap.size); // 2;
533
+ * heap.poll();
534
+ * console.log(heap.size); // 1;
535
+ */
467
536
  get size() {
468
537
  return this.elements.length;
469
538
  }
@@ -501,21 +570,61 @@ var Heap = class _Heap extends IterableElementBase {
501
570
  return new _Heap(elements, options);
502
571
  }
503
572
  /**
504
- * Insert an element.
505
- * @remarks Time O(1) amortized, Space O(1)
506
- * @param element - Element to insert.
507
- * @returns True.
508
- */
573
+ * Insert an element.
574
+ * @remarks Time O(1) amortized, Space O(1)
575
+ * @param element - Element to insert.
576
+ * @returns True.
577
+
578
+
579
+
580
+
581
+
582
+
583
+
584
+
585
+
586
+
587
+
588
+ * @example
589
+ * // basic Heap creation and add operation
590
+ * // Create a min heap (default)
591
+ * const minHeap = new Heap([5, 3, 7, 1, 9, 2]);
592
+ *
593
+ * // Verify size
594
+ * console.log(minHeap.size); // 6;
595
+ *
596
+ * // Add new element
597
+ * minHeap.add(4);
598
+ * console.log(minHeap.size); // 7;
599
+ *
600
+ * // Min heap property: smallest element at root
601
+ * const min = minHeap.peek();
602
+ * console.log(min); // 1;
603
+ */
509
604
  add(element) {
510
605
  this._elements.push(element);
511
606
  return this._bubbleUp(this.elements.length - 1);
512
607
  }
513
608
  /**
514
- * Insert many elements from an iterable.
515
- * @remarks Time O(N log N), Space O(1)
516
- * @param elements - Iterable of elements or raw values.
517
- * @returns Array of per-element success flags.
518
- */
609
+ * Insert many elements from an iterable.
610
+ * @remarks Time O(N log N), Space O(1)
611
+ * @param elements - Iterable of elements or raw values.
612
+ * @returns Array of per-element success flags.
613
+
614
+
615
+
616
+
617
+
618
+
619
+
620
+
621
+ * @example
622
+ * // Add multiple elements
623
+ * const heap = new Heap<number>([], { comparator: (a, b) => a - b });
624
+ * heap.addMany([5, 3, 7, 1]);
625
+ * console.log(heap.peek()); // 1;
626
+ * console.log(heap.size); // 4;
627
+ */
519
628
  addMany(elements) {
520
629
  const flags = [];
521
630
  for (const el of elements) {
@@ -530,10 +639,46 @@ var Heap = class _Heap extends IterableElementBase {
530
639
  return flags;
531
640
  }
532
641
  /**
533
- * Remove and return the top element.
534
- * @remarks Time O(log N), Space O(1)
535
- * @returns Top element or undefined.
536
- */
642
+ * Remove and return the top element.
643
+ * @remarks Time O(log N), Space O(1)
644
+ * @returns Top element or undefined.
645
+
646
+
647
+
648
+
649
+
650
+
651
+
652
+
653
+
654
+
655
+
656
+ * @example
657
+ * // Heap with custom comparator (MaxHeap behavior)
658
+ * interface Task {
659
+ * id: number;
660
+ * priority: number;
661
+ * name: string;
662
+ * }
663
+ *
664
+ * // Custom comparator for max heap behavior (higher priority first)
665
+ * const tasks: Task[] = [
666
+ * { id: 1, priority: 5, name: 'Email' },
667
+ * { id: 2, priority: 3, name: 'Chat' },
668
+ * { id: 3, priority: 8, name: 'Alert' }
669
+ * ];
670
+ *
671
+ * const maxHeap = new Heap(tasks, {
672
+ * comparator: (a: Task, b: Task) => b.priority - a.priority
673
+ * });
674
+ *
675
+ * console.log(maxHeap.size); // 3;
676
+ *
677
+ * // Peek returns highest priority task
678
+ * const topTask = maxHeap.peek();
679
+ * console.log(topTask?.priority); // 8;
680
+ * console.log(topTask?.name); // 'Alert';
681
+ */
537
682
  poll() {
538
683
  if (this.elements.length === 0) return;
539
684
  const value = this.elements[0];
@@ -545,26 +690,125 @@ var Heap = class _Heap extends IterableElementBase {
545
690
  return value;
546
691
  }
547
692
  /**
548
- * Get the current top element without removing it.
549
- * @remarks Time O(1), Space O(1)
550
- * @returns Top element or undefined.
551
- */
693
+ * Get the current top element without removing it.
694
+ * @remarks Time O(1), Space O(1)
695
+ * @returns Top element or undefined.
696
+
697
+
698
+
699
+
700
+
701
+
702
+
703
+
704
+
705
+
706
+
707
+ * @example
708
+ * // Heap for event processing with priority
709
+ * interface Event {
710
+ * id: number;
711
+ * type: 'critical' | 'warning' | 'info';
712
+ * timestamp: number;
713
+ * message: string;
714
+ * }
715
+ *
716
+ * // Custom priority: critical > warning > info
717
+ * const priorityMap = { critical: 3, warning: 2, info: 1 };
718
+ *
719
+ * const eventHeap = new Heap<Event>([], {
720
+ * comparator: (a: Event, b: Event) => {
721
+ * const priorityA = priorityMap[a.type];
722
+ * const priorityB = priorityMap[b.type];
723
+ * return priorityB - priorityA; // Higher priority first
724
+ * }
725
+ * });
726
+ *
727
+ * // Add events in random order
728
+ * eventHeap.add({ id: 1, type: 'info', timestamp: 100, message: 'User logged in' });
729
+ * eventHeap.add({ id: 2, type: 'critical', timestamp: 101, message: 'Server down' });
730
+ * eventHeap.add({ id: 3, type: 'warning', timestamp: 102, message: 'High memory' });
731
+ * eventHeap.add({ id: 4, type: 'info', timestamp: 103, message: 'Cache cleared' });
732
+ * eventHeap.add({ id: 5, type: 'critical', timestamp: 104, message: 'Database error' });
733
+ *
734
+ * console.log(eventHeap.size); // 5;
735
+ *
736
+ * // Process events by priority (critical first)
737
+ * const processedOrder: Event[] = [];
738
+ * while (eventHeap.size > 0) {
739
+ * const event = eventHeap.poll();
740
+ * if (event) {
741
+ * processedOrder.push(event);
742
+ * }
743
+ * }
744
+ *
745
+ * // Verify critical events came first
746
+ * console.log(processedOrder[0].type); // 'critical';
747
+ * console.log(processedOrder[1].type); // 'critical';
748
+ * console.log(processedOrder[2].type); // 'warning';
749
+ * console.log(processedOrder[3].type); // 'info';
750
+ * console.log(processedOrder[4].type); // 'info';
751
+ *
752
+ * // Verify O(log n) operations
753
+ * const newHeap = new Heap<number>([5, 3, 7, 1]);
754
+ *
755
+ * // Add - O(log n)
756
+ * newHeap.add(2);
757
+ * console.log(newHeap.size); // 5;
758
+ *
759
+ * // Poll - O(log n)
760
+ * const removed = newHeap.poll();
761
+ * console.log(removed); // 1;
762
+ *
763
+ * // Peek - O(1)
764
+ * const top = newHeap.peek();
765
+ * console.log(top); // 2;
766
+ */
552
767
  peek() {
553
768
  return this.elements[0];
554
769
  }
555
770
  /**
556
- * Check whether the heap is empty.
557
- * @remarks Time O(1), Space O(1)
558
- * @returns True if size is 0.
559
- */
771
+ * Check whether the heap is empty.
772
+ * @remarks Time O(1), Space O(1)
773
+ * @returns True if size is 0.
774
+
775
+
776
+
777
+
778
+
779
+
780
+
781
+
782
+
783
+ * @example
784
+ * // Check if heap is empty
785
+ * const heap = new Heap<number>([], { comparator: (a, b) => a - b });
786
+ * console.log(heap.isEmpty()); // true;
787
+ * heap.add(1);
788
+ * console.log(heap.isEmpty()); // false;
789
+ */
560
790
  isEmpty() {
561
791
  return this.size === 0;
562
792
  }
563
793
  /**
564
- * Remove all elements.
565
- * @remarks Time O(1), Space O(1)
566
- * @returns void
567
- */
794
+ * Remove all elements.
795
+ * @remarks Time O(1), Space O(1)
796
+ * @returns void
797
+
798
+
799
+
800
+
801
+
802
+
803
+
804
+
805
+
806
+ * @example
807
+ * // Remove all elements
808
+ * const heap = new Heap<number>([1, 2, 3], { comparator: (a, b) => a - b });
809
+ * heap.clear();
810
+ * console.log(heap.isEmpty()); // true;
811
+ */
568
812
  clear() {
569
813
  this._elements = [];
570
814
  }
@@ -579,21 +823,41 @@ var Heap = class _Heap extends IterableElementBase {
579
823
  return this.fix();
580
824
  }
581
825
  /**
582
- * Check if an equal element exists in the heap.
583
- * @remarks Time O(N), Space O(1)
584
- * @param element - Element to search for.
585
- * @returns True if found.
586
- */
826
+ * Check if an equal element exists in the heap.
827
+ * @remarks Time O(N), Space O(1)
828
+ * @param element - Element to search for.
829
+ * @returns True if found.
830
+
831
+
832
+ * @example
833
+ * // Check element existence
834
+ * const heap = new Heap<number>([3, 1, 2], { comparator: (a, b) => a - b });
835
+ * console.log(heap.has(1)); // true;
836
+ * console.log(heap.has(99)); // false;
837
+ */
587
838
  has(element) {
588
839
  for (const el of this.elements) if (this._equals(el, element)) return true;
589
840
  return false;
590
841
  }
591
842
  /**
592
- * Delete one occurrence of an element.
593
- * @remarks Time O(N), Space O(1)
594
- * @param element - Element to delete.
595
- * @returns True if an element was removed.
596
- */
843
+ * Delete one occurrence of an element.
844
+ * @remarks Time O(N), Space O(1)
845
+ * @param element - Element to delete.
846
+ * @returns True if an element was removed.
847
+
848
+
849
+
850
+
851
+
852
+
853
+
854
+
855
+ * @example
856
+ * // Remove specific element
857
+ * const heap = new Heap<number>([3, 1, 4, 1, 5], { comparator: (a, b) => a - b });
858
+ * heap.delete(4);
859
+ * console.log(heap.toArray().includes(4)); // false;
860
+ */
597
861
  delete(element) {
598
862
  let index = -1;
599
863
  for (let i = 0; i < this.elements.length; i++) {
@@ -651,11 +915,18 @@ var Heap = class _Heap extends IterableElementBase {
651
915
  return this;
652
916
  }
653
917
  /**
654
- * Traverse the binary heap as a complete binary tree and collect elements.
655
- * @remarks Time O(N), Space O(H)
656
- * @param [order] - Traversal order: 'PRE' | 'IN' | 'POST'.
657
- * @returns Array of visited elements.
658
- */
918
+ * Traverse the binary heap as a complete binary tree and collect elements.
919
+ * @remarks Time O(N), Space O(H)
920
+ * @param [order] - Traversal order: 'PRE' | 'IN' | 'POST'.
921
+ * @returns Array of visited elements.
922
+
923
+
924
+ * @example
925
+ * // Depth-first traversal
926
+ * const heap = new Heap<number>([3, 1, 2], { comparator: (a, b) => a - b });
927
+ * const result = heap.dfs('IN');
928
+ * console.log(result.length); // 3;
929
+ */
659
930
  dfs(order = "PRE") {
660
931
  const result = [];
661
932
  const _dfs = /* @__PURE__ */ __name((index) => {
@@ -692,10 +963,26 @@ var Heap = class _Heap extends IterableElementBase {
692
963
  return results;
693
964
  }
694
965
  /**
695
- * Return all elements in ascending order by repeatedly polling.
696
- * @remarks Time O(N log N), Space O(N)
697
- * @returns Sorted array of elements.
698
- */
966
+ * Return all elements in ascending order by repeatedly polling.
967
+ * @remarks Time O(N log N), Space O(N)
968
+ * @returns Sorted array of elements.
969
+
970
+
971
+
972
+
973
+
974
+
975
+
976
+
977
+
978
+
979
+
980
+ * @example
981
+ * // Sort elements using heap
982
+ * const heap = new Heap<number>([5, 1, 3, 2, 4]);
983
+ * const sorted = heap.sort();
984
+ * console.log(sorted); // [1, 2, 3, 4, 5];
985
+ */
699
986
  sort() {
700
987
  const visited = [];
701
988
  const cloned = this._createInstance();
@@ -707,22 +994,52 @@ var Heap = class _Heap extends IterableElementBase {
707
994
  return visited;
708
995
  }
709
996
  /**
710
- * Deep clone this heap.
711
- * @remarks Time O(N), Space O(N)
712
- * @returns A new heap with the same elements.
713
- */
997
+ * Deep clone this heap.
998
+ * @remarks Time O(N), Space O(N)
999
+ * @returns A new heap with the same elements.
1000
+
1001
+
1002
+
1003
+
1004
+
1005
+
1006
+
1007
+
1008
+
1009
+ * @example
1010
+ * // Create independent copy
1011
+ * const heap = new Heap<number>([3, 1, 4], { comparator: (a, b) => a - b });
1012
+ * const copy = heap.clone();
1013
+ * copy.poll();
1014
+ * console.log(heap.size); // 3;
1015
+ * console.log(copy.size); // 2;
1016
+ */
714
1017
  clone() {
715
1018
  const next = this._createInstance();
716
1019
  for (const x of this.elements) next.add(x);
717
1020
  return next;
718
1021
  }
719
1022
  /**
720
- * Filter elements into a new heap of the same class.
721
- * @remarks Time O(N log N), Space O(N)
722
- * @param callback - Predicate (element, index, heap) → boolean to keep element.
723
- * @param [thisArg] - Value for `this` inside the callback.
724
- * @returns A new heap with the kept elements.
725
- */
1023
+ * Filter elements into a new heap of the same class.
1024
+ * @remarks Time O(N log N), Space O(N)
1025
+ * @param callback - Predicate (element, index, heap) → boolean to keep element.
1026
+ * @param [thisArg] - Value for `this` inside the callback.
1027
+ * @returns A new heap with the kept elements.
1028
+
1029
+
1030
+
1031
+
1032
+
1033
+
1034
+
1035
+
1036
+
1037
+ * @example
1038
+ * // Filter elements
1039
+ * const heap = new Heap<number>([1, 2, 3, 4, 5], { comparator: (a, b) => a - b });
1040
+ * const evens = heap.filter(x => x % 2 === 0);
1041
+ * console.log(evens.size); // 2;
1042
+ */
726
1043
  filter(callback, thisArg) {
727
1044
  const out = this._createInstance();
728
1045
  let i = 0;
@@ -736,18 +1053,31 @@ var Heap = class _Heap extends IterableElementBase {
736
1053
  return out;
737
1054
  }
738
1055
  /**
739
- * Map elements into a new heap of possibly different element type.
740
- * @remarks Time O(N log N), Space O(N)
741
- * @template EM
742
- * @template RM
743
- * @param callback - Mapping function (element, index, heap) → newElement.
744
- * @param options - Options for the output heap, including comparator for EM.
745
- * @param [thisArg] - Value for `this` inside the callback.
746
- * @returns A new heap with mapped elements.
747
- */
1056
+ * Map elements into a new heap of possibly different element type.
1057
+ * @remarks Time O(N log N), Space O(N)
1058
+ * @template EM
1059
+ * @template RM
1060
+ * @param callback - Mapping function (element, index, heap) → newElement.
1061
+ * @param options - Options for the output heap, including comparator for EM.
1062
+ * @param [thisArg] - Value for `this` inside the callback.
1063
+ * @returns A new heap with mapped elements.
1064
+
1065
+
1066
+
1067
+
1068
+
1069
+
1070
+
1071
+
1072
+ * @example
1073
+ * // Transform elements
1074
+ * const heap = new Heap<number>([1, 2, 3], { comparator: (a, b) => a - b });
1075
+ * const doubled = heap.map(x => x * 2, { comparator: (a, b) => a - b });
1076
+ * console.log(doubled.peek()); // 2;
1077
+ */
748
1078
  map(callback, options, thisArg) {
749
1079
  const { comparator, toElementFn, ...rest } = options ?? {};
750
- if (!comparator) throw new TypeError("Heap.map requires options.comparator for EM");
1080
+ if (!comparator) throw new TypeError(ERR.comparatorRequired("Heap.map"));
751
1081
  const out = this._createLike([], { ...rest, comparator, toElementFn });
752
1082
  let i = 0;
753
1083
  for (const x of this) {
@@ -774,7 +1104,7 @@ var Heap = class _Heap extends IterableElementBase {
774
1104
  }
775
1105
  _DEFAULT_COMPARATOR = /* @__PURE__ */ __name((a, b) => {
776
1106
  if (typeof a === "object" || typeof b === "object") {
777
- throw TypeError("When comparing object types, define a custom comparator in options.");
1107
+ throw new TypeError(ERR.comparatorRequired("Heap"));
778
1108
  }
779
1109
  if (a > b) return 1;
780
1110
  if (a < b) return -1;
@@ -1107,18 +1437,52 @@ var Queue = class _Queue extends LinearBase {
1107
1437
  this._autoCompactRatio = value;
1108
1438
  }
1109
1439
  /**
1110
- * Get the number of elements currently in the queue.
1111
- * @remarks Time O(1), Space O(1)
1112
- * @returns Current length.
1113
- */
1440
+ * Get the number of elements currently in the queue.
1441
+ * @remarks Time O(1), Space O(1)
1442
+ * @returns Current length.
1443
+
1444
+
1445
+
1446
+
1447
+
1448
+
1449
+
1450
+
1451
+
1452
+
1453
+
1454
+ * @example
1455
+ * // Track queue length
1456
+ * const q = new Queue<number>();
1457
+ * console.log(q.length); // 0;
1458
+ * q.push(1);
1459
+ * q.push(2);
1460
+ * console.log(q.length); // 2;
1461
+ */
1114
1462
  get length() {
1115
1463
  return this.elements.length - this._offset;
1116
1464
  }
1117
1465
  /**
1118
- * Get the first element (front) without removing it.
1119
- * @remarks Time O(1), Space O(1)
1120
- * @returns Front element or undefined.
1121
- */
1466
+ * Get the first element (front) without removing it.
1467
+ * @remarks Time O(1), Space O(1)
1468
+ * @returns Front element or undefined.
1469
+
1470
+
1471
+
1472
+
1473
+
1474
+
1475
+
1476
+
1477
+
1478
+
1479
+
1480
+ * @example
1481
+ * // View the front element
1482
+ * const q = new Queue<string>(['first', 'second', 'third']);
1483
+ * console.log(q.first); // 'first';
1484
+ * console.log(q.length); // 3;
1485
+ */
1122
1486
  get first() {
1123
1487
  return this.length > 0 ? this.elements[this._offset] : void 0;
1124
1488
  }
@@ -1141,19 +1505,69 @@ var Queue = class _Queue extends LinearBase {
1141
1505
  return new _Queue(elements);
1142
1506
  }
1143
1507
  /**
1144
- * Check whether the queue is empty.
1145
- * @remarks Time O(1), Space O(1)
1146
- * @returns True if length is 0.
1147
- */
1508
+ * Check whether the queue is empty.
1509
+ * @remarks Time O(1), Space O(1)
1510
+ * @returns True if length is 0.
1511
+
1512
+
1513
+
1514
+
1515
+
1516
+
1517
+
1518
+
1519
+
1520
+
1521
+
1522
+ * @example
1523
+ * // Queue for...of iteration and isEmpty check
1524
+ * const queue = new Queue<string>(['A', 'B', 'C', 'D']);
1525
+ *
1526
+ * const elements: string[] = [];
1527
+ * for (const item of queue) {
1528
+ * elements.push(item);
1529
+ * }
1530
+ *
1531
+ * // Verify all elements are iterated in order
1532
+ * console.log(elements); // ['A', 'B', 'C', 'D'];
1533
+ *
1534
+ * // Process all elements
1535
+ * while (queue.length > 0) {
1536
+ * queue.shift();
1537
+ * }
1538
+ *
1539
+ * console.log(queue.length); // 0;
1540
+ */
1148
1541
  isEmpty() {
1149
1542
  return this.length === 0;
1150
1543
  }
1151
1544
  /**
1152
- * Enqueue one element at the back.
1153
- * @remarks Time O(1), Space O(1)
1154
- * @param element - Element to enqueue.
1155
- * @returns True on success.
1156
- */
1545
+ * Enqueue one element at the back.
1546
+ * @remarks Time O(1), Space O(1)
1547
+ * @param element - Element to enqueue.
1548
+ * @returns True on success.
1549
+
1550
+
1551
+
1552
+
1553
+
1554
+
1555
+
1556
+
1557
+
1558
+
1559
+
1560
+ * @example
1561
+ * // basic Queue creation and push operation
1562
+ * // Create a simple Queue with initial values
1563
+ * const queue = new Queue([1, 2, 3, 4, 5]);
1564
+ *
1565
+ * // Verify the queue maintains insertion order
1566
+ * console.log([...queue]); // [1, 2, 3, 4, 5];
1567
+ *
1568
+ * // Check length
1569
+ * console.log(queue.length); // 5;
1570
+ */
1157
1571
  push(element) {
1158
1572
  this.elements.push(element);
1159
1573
  if (this._maxLen > 0 && this.length > this._maxLen) this.shift();
@@ -1174,10 +1588,35 @@ var Queue = class _Queue extends LinearBase {
1174
1588
  return ans;
1175
1589
  }
1176
1590
  /**
1177
- * Dequeue one element from the front (amortized via offset).
1178
- * @remarks Time O(1) amortized, Space O(1)
1179
- * @returns Removed element or undefined.
1180
- */
1591
+ * Dequeue one element from the front (amortized via offset).
1592
+ * @remarks Time O(1) amortized, Space O(1)
1593
+ * @returns Removed element or undefined.
1594
+
1595
+
1596
+
1597
+
1598
+
1599
+
1600
+
1601
+
1602
+
1603
+
1604
+
1605
+ * @example
1606
+ * // Queue shift and peek operations
1607
+ * const queue = new Queue<number>([10, 20, 30, 40]);
1608
+ *
1609
+ * // Peek at the front element without removing it
1610
+ * console.log(queue.first); // 10;
1611
+ *
1612
+ * // Remove and get the first element (FIFO)
1613
+ * const first = queue.shift();
1614
+ * console.log(first); // 10;
1615
+ *
1616
+ * // Verify remaining elements and length decreased
1617
+ * console.log([...queue]); // [20, 30, 40];
1618
+ * console.log(queue.length); // 3;
1619
+ */
1181
1620
  shift() {
1182
1621
  if (this.length === 0) return void 0;
1183
1622
  const first = this.first;
@@ -1186,11 +1625,24 @@ var Queue = class _Queue extends LinearBase {
1186
1625
  return first;
1187
1626
  }
1188
1627
  /**
1189
- * Delete the first occurrence of a specific element.
1190
- * @remarks Time O(N), Space O(1)
1191
- * @param element - Element to remove (strict equality via Object.is).
1192
- * @returns True if an element was removed.
1193
- */
1628
+ * Delete the first occurrence of a specific element.
1629
+ * @remarks Time O(N), Space O(1)
1630
+ * @param element - Element to remove (strict equality via Object.is).
1631
+ * @returns True if an element was removed.
1632
+
1633
+
1634
+
1635
+
1636
+
1637
+
1638
+
1639
+
1640
+ * @example
1641
+ * // Remove specific element
1642
+ * const q = new Queue<number>([1, 2, 3, 2]);
1643
+ * q.delete(2);
1644
+ * console.log(q.length); // 3;
1645
+ */
1194
1646
  delete(element) {
1195
1647
  for (let i = this._offset; i < this.elements.length; i++) {
1196
1648
  if (Object.is(this.elements[i], element)) {
@@ -1201,11 +1653,24 @@ var Queue = class _Queue extends LinearBase {
1201
1653
  return false;
1202
1654
  }
1203
1655
  /**
1204
- * Get the element at a given logical index.
1205
- * @remarks Time O(1), Space O(1)
1206
- * @param index - Zero-based index from the front.
1207
- * @returns Element or undefined.
1208
- */
1656
+ * Get the element at a given logical index.
1657
+ * @remarks Time O(1), Space O(1)
1658
+ * @param index - Zero-based index from the front.
1659
+ * @returns Element or undefined.
1660
+
1661
+
1662
+
1663
+
1664
+
1665
+
1666
+
1667
+
1668
+ * @example
1669
+ * // Access element by index
1670
+ * const q = new Queue<string>(['a', 'b', 'c']);
1671
+ * console.log(q.at(0)); // 'a';
1672
+ * console.log(q.at(2)); // 'c';
1673
+ */
1209
1674
  at(index) {
1210
1675
  if (index < 0 || index >= this.length) return void 0;
1211
1676
  return this._elements[this._offset + index];
@@ -1257,19 +1722,48 @@ var Queue = class _Queue extends LinearBase {
1257
1722
  return this;
1258
1723
  }
1259
1724
  /**
1260
- * Remove all elements and reset offset.
1261
- * @remarks Time O(1), Space O(1)
1262
- * @returns void
1263
- */
1725
+ * Remove all elements and reset offset.
1726
+ * @remarks Time O(1), Space O(1)
1727
+ * @returns void
1728
+
1729
+
1730
+
1731
+
1732
+
1733
+
1734
+
1735
+
1736
+
1737
+ * @example
1738
+ * // Remove all elements
1739
+ * const q = new Queue<number>([1, 2, 3]);
1740
+ * q.clear();
1741
+ * console.log(q.length); // 0;
1742
+ */
1264
1743
  clear() {
1265
1744
  this._elements = [];
1266
1745
  this._offset = 0;
1267
1746
  }
1268
1747
  /**
1269
- * Compact storage by discarding consumed head elements.
1270
- * @remarks Time O(N), Space O(N)
1271
- * @returns True when compaction performed.
1272
- */
1748
+ * Compact storage by discarding consumed head elements.
1749
+ * @remarks Time O(N), Space O(N)
1750
+ * @returns True when compaction performed.
1751
+
1752
+
1753
+
1754
+
1755
+
1756
+
1757
+
1758
+
1759
+ * @example
1760
+ * // Reclaim unused memory
1761
+ * const q = new Queue<number>([1, 2, 3, 4, 5]);
1762
+ * q.shift();
1763
+ * q.shift();
1764
+ * q.compact();
1765
+ * console.log(q.length); // 3;
1766
+ */
1273
1767
  compact() {
1274
1768
  this._elements = this.elements.slice(this._offset);
1275
1769
  this._offset = 0;
@@ -1295,10 +1789,26 @@ var Queue = class _Queue extends LinearBase {
1295
1789
  return removed;
1296
1790
  }
1297
1791
  /**
1298
- * Deep clone this queue and its parameters.
1299
- * @remarks Time O(N), Space O(N)
1300
- * @returns A new queue with the same content and options.
1301
- */
1792
+ * Deep clone this queue and its parameters.
1793
+ * @remarks Time O(N), Space O(N)
1794
+ * @returns A new queue with the same content and options.
1795
+
1796
+
1797
+
1798
+
1799
+
1800
+
1801
+
1802
+
1803
+
1804
+ * @example
1805
+ * // Create independent copy
1806
+ * const q = new Queue<number>([1, 2, 3]);
1807
+ * const copy = q.clone();
1808
+ * copy.shift();
1809
+ * console.log(q.length); // 3;
1810
+ * console.log(copy.length); // 2;
1811
+ */
1302
1812
  clone() {
1303
1813
  const out = this._createInstance({ toElementFn: this.toElementFn, maxLen: this._maxLen });
1304
1814
  out._setAutoCompactRatio(this._autoCompactRatio);
@@ -1306,12 +1816,26 @@ var Queue = class _Queue extends LinearBase {
1306
1816
  return out;
1307
1817
  }
1308
1818
  /**
1309
- * Filter elements into a new queue of the same class.
1310
- * @remarks Time O(N), Space O(N)
1311
- * @param predicate - Predicate (element, index, queue) → boolean to keep element.
1312
- * @param [thisArg] - Value for `this` inside the predicate.
1313
- * @returns A new queue with kept elements.
1314
- */
1819
+ * Filter elements into a new queue of the same class.
1820
+ * @remarks Time O(N), Space O(N)
1821
+ * @param predicate - Predicate (element, index, queue) → boolean to keep element.
1822
+ * @param [thisArg] - Value for `this` inside the predicate.
1823
+ * @returns A new queue with kept elements.
1824
+
1825
+
1826
+
1827
+
1828
+
1829
+
1830
+
1831
+
1832
+
1833
+ * @example
1834
+ * // Filter elements
1835
+ * const q = new Queue<number>([1, 2, 3, 4, 5]);
1836
+ * const evens = q.filter(x => x % 2 === 0);
1837
+ * console.log(evens.length); // 2;
1838
+ */
1315
1839
  filter(predicate, thisArg) {
1316
1840
  const out = this._createInstance({ toElementFn: this.toElementFn, maxLen: this._maxLen });
1317
1841
  out._setAutoCompactRatio(this._autoCompactRatio);
@@ -1323,15 +1847,28 @@ var Queue = class _Queue extends LinearBase {
1323
1847
  return out;
1324
1848
  }
1325
1849
  /**
1326
- * Map each element to a new element in a possibly different-typed queue.
1327
- * @remarks Time O(N), Space O(N)
1328
- * @template EM
1329
- * @template RM
1330
- * @param callback - Mapping function (element, index, queue) → newElement.
1331
- * @param [options] - Options for the output queue (e.g., toElementFn, maxLen, autoCompactRatio).
1332
- * @param [thisArg] - Value for `this` inside the callback.
1333
- * @returns A new Queue with mapped elements.
1334
- */
1850
+ * Map each element to a new element in a possibly different-typed queue.
1851
+ * @remarks Time O(N), Space O(N)
1852
+ * @template EM
1853
+ * @template RM
1854
+ * @param callback - Mapping function (element, index, queue) → newElement.
1855
+ * @param [options] - Options for the output queue (e.g., toElementFn, maxLen, autoCompactRatio).
1856
+ * @param [thisArg] - Value for `this` inside the callback.
1857
+ * @returns A new Queue with mapped elements.
1858
+
1859
+
1860
+
1861
+
1862
+
1863
+
1864
+
1865
+
1866
+ * @example
1867
+ * // Transform elements
1868
+ * const q = new Queue<number>([1, 2, 3]);
1869
+ * const doubled = q.map(x => x * 2);
1870
+ * console.log(doubled.toArray()); // [2, 4, 6];
1871
+ */
1335
1872
  map(callback, options, thisArg) {
1336
1873
  const out = new this.constructor([], {
1337
1874
  toElementFn: options?.toElementFn,
@@ -1561,7 +2098,7 @@ var AbstractGraph = class extends IterableEntryBase {
1561
2098
  const newEdge = this.createEdge(srcOrEdge, dest, weight, value);
1562
2099
  return this._addEdge(newEdge);
1563
2100
  } else {
1564
- throw new Error("dest must be a Vertex or vertex key while srcOrEdge is an Edge");
2101
+ throw new TypeError(ERR.invalidArgument("dest must be a Vertex or vertex key when srcOrEdge is an Edge.", "Graph"));
1565
2102
  }
1566
2103
  }
1567
2104
  }
@@ -2241,6 +2778,92 @@ var AbstractGraph = class extends IterableEntryBase {
2241
2778
  _getVertexKey(vertexOrKey) {
2242
2779
  return vertexOrKey instanceof AbstractVertex ? vertexOrKey.key : vertexOrKey;
2243
2780
  }
2781
+ /**
2782
+ * The edge connector string used in visual output.
2783
+ * Override in subclasses (e.g., '--' for undirected, '->' for directed).
2784
+ */
2785
+ get _edgeConnector() {
2786
+ return "--";
2787
+ }
2788
+ /**
2789
+ * Generate a text-based visual representation of the graph.
2790
+ *
2791
+ * **Adjacency list format:**
2792
+ * ```
2793
+ * Graph (5 vertices, 6 edges):
2794
+ * A -> B (1), C (2)
2795
+ * B -> D (3)
2796
+ * C -> (no outgoing edges)
2797
+ * D -> A (1)
2798
+ * E (isolated)
2799
+ * ```
2800
+ *
2801
+ * @param options - Optional display settings.
2802
+ * @param options.showWeight - Whether to show edge weights (default: true).
2803
+ * @returns The visual string.
2804
+ */
2805
+ toVisual(options) {
2806
+ const showWeight = options?.showWeight ?? true;
2807
+ const vertices = [...this._vertexMap.values()];
2808
+ const vertexCount = vertices.length;
2809
+ const edgeCount = this.edgeSet().length;
2810
+ const lines = [`Graph (${vertexCount} vertices, ${edgeCount} edges):`];
2811
+ for (const vertex of vertices) {
2812
+ const neighbors = this.getNeighbors(vertex);
2813
+ if (neighbors.length === 0) {
2814
+ lines.push(` ${vertex.key} (isolated)`);
2815
+ } else {
2816
+ const edgeStrs = neighbors.map((neighbor) => {
2817
+ const edge = this.getEdge(vertex, neighbor);
2818
+ if (edge && showWeight && edge.weight !== void 0 && edge.weight !== 1) {
2819
+ return `${neighbor.key} (${edge.weight})`;
2820
+ }
2821
+ return `${neighbor.key}`;
2822
+ });
2823
+ lines.push(` ${vertex.key} ${this._edgeConnector} ${edgeStrs.join(", ")}`);
2824
+ }
2825
+ }
2826
+ return lines.join("\n");
2827
+ }
2828
+ /**
2829
+ * Generate DOT language representation for Graphviz.
2830
+ *
2831
+ * @param options - Optional display settings.
2832
+ * @param options.name - Graph name (default: 'G').
2833
+ * @param options.showWeight - Whether to label edges with weight (default: true).
2834
+ * @returns DOT format string.
2835
+ */
2836
+ toDot(options) {
2837
+ const name = options?.name ?? "G";
2838
+ const showWeight = options?.showWeight ?? true;
2839
+ const isDirected = this._edgeConnector === "->";
2840
+ const graphType = isDirected ? "digraph" : "graph";
2841
+ const edgeOp = isDirected ? "->" : "--";
2842
+ const lines = [`${graphType} ${name} {`];
2843
+ for (const vertex of this._vertexMap.values()) {
2844
+ lines.push(` "${vertex.key}";`);
2845
+ }
2846
+ const visited = /* @__PURE__ */ new Set();
2847
+ for (const vertex of this._vertexMap.values()) {
2848
+ for (const neighbor of this.getNeighbors(vertex)) {
2849
+ const edgeId = isDirected ? `${vertex.key}->${neighbor.key}` : [vertex.key, neighbor.key].sort().join("--");
2850
+ if (visited.has(edgeId)) continue;
2851
+ visited.add(edgeId);
2852
+ const edge = this.getEdge(vertex, neighbor);
2853
+ const label = edge && showWeight && edge.weight !== void 0 && edge.weight !== 1 ? ` [label="${edge.weight}"]` : "";
2854
+ lines.push(` "${vertex.key}" ${edgeOp} "${neighbor.key}"${label};`);
2855
+ }
2856
+ }
2857
+ lines.push("}");
2858
+ return lines.join("\n");
2859
+ }
2860
+ /**
2861
+ * Print the graph to console.
2862
+ * @param options - Display settings passed to `toVisual`.
2863
+ */
2864
+ print(options) {
2865
+ console.log(this.toVisual(options));
2866
+ }
2244
2867
  };
2245
2868
 
2246
2869
  // src/data-structures/graph/directed-graph.ts
@@ -2276,6 +2899,9 @@ var DirectedGraph = class _DirectedGraph extends AbstractGraph {
2276
2899
  constructor(options) {
2277
2900
  super(options);
2278
2901
  }
2902
+ get _edgeConnector() {
2903
+ return "->";
2904
+ }
2279
2905
  _outEdgeMap = /* @__PURE__ */ new Map();
2280
2906
  get outEdgeMap() {
2281
2907
  return this._outEdgeMap;
@@ -2339,12 +2965,28 @@ var DirectedGraph = class _DirectedGraph extends AbstractGraph {
2339
2965
  return new DirectedEdge(src, dest, weight ?? this.options.defaultEdgeWeight ?? 1, value);
2340
2966
  }
2341
2967
  /**
2342
- * Get the unique edge from `src` to `dest`, if present.
2343
- * @param srcOrKey - Source vertex or key.
2344
- * @param destOrKey - Destination vertex or key.
2345
- * @returns Edge instance or `undefined`.
2346
- * @remarks Time O(1) avg, Space O(1)
2347
- */
2968
+ * Get the unique edge from `src` to `dest`, if present.
2969
+ * @param srcOrKey - Source vertex or key.
2970
+ * @param destOrKey - Destination vertex or key.
2971
+ * @returns Edge instance or `undefined`.
2972
+ * @remarks Time O(1) avg, Space O(1)
2973
+
2974
+
2975
+
2976
+
2977
+
2978
+
2979
+
2980
+
2981
+ * @example
2982
+ * // Get edge between vertices
2983
+ * const g = new DirectedGraph();
2984
+ * g.addVertex('A');
2985
+ * g.addVertex('B');
2986
+ * g.addEdge('A', 'B', 5);
2987
+ * const edge = g.getEdge('A', 'B');
2988
+ * console.log(edge?.weight); // 5;
2989
+ */
2348
2990
  getEdge(srcOrKey, destOrKey) {
2349
2991
  let edgeMap = [];
2350
2992
  if (srcOrKey !== void 0 && destOrKey !== void 0) {
@@ -2384,12 +3026,48 @@ var DirectedGraph = class _DirectedGraph extends AbstractGraph {
2384
3026
  return removed;
2385
3027
  }
2386
3028
  /**
2387
- * Delete an edge by instance or by `(srcKey, destKey)`.
2388
- * @param edgeOrSrcVertexKey - Edge instance or source vertex/key.
2389
- * @param destVertexKey - Optional destination vertex/key when deleting by pair.
2390
- * @returns Removed edge or `undefined`.
2391
- * @remarks Time O(1) avg, Space O(1)
2392
- */
3029
+ * Delete an edge by instance or by `(srcKey, destKey)`.
3030
+ * @param edgeOrSrcVertexKey - Edge instance or source vertex/key.
3031
+ * @param destVertexKey - Optional destination vertex/key when deleting by pair.
3032
+ * @returns Removed edge or `undefined`.
3033
+ * @remarks Time O(1) avg, Space O(1)
3034
+
3035
+
3036
+
3037
+
3038
+
3039
+
3040
+
3041
+
3042
+
3043
+
3044
+
3045
+ * @example
3046
+ * // DirectedGraph deleteEdge and vertex operations
3047
+ * const graph = new DirectedGraph<string>();
3048
+ *
3049
+ * // Build a small graph
3050
+ * graph.addVertex('X');
3051
+ * graph.addVertex('Y');
3052
+ * graph.addVertex('Z');
3053
+ * graph.addEdge('X', 'Y', 1);
3054
+ * graph.addEdge('Y', 'Z', 2);
3055
+ *
3056
+ * // Delete an edge
3057
+ * graph.deleteEdgeSrcToDest('X', 'Y');
3058
+ * console.log(graph.hasEdge('X', 'Y')); // false;
3059
+ *
3060
+ * // Edge in other direction should not exist
3061
+ * console.log(graph.hasEdge('Y', 'X')); // false;
3062
+ *
3063
+ * // Other edges should remain
3064
+ * console.log(graph.hasEdge('Y', 'Z')); // true;
3065
+ *
3066
+ * // Delete a vertex
3067
+ * graph.deleteVertex('Y');
3068
+ * console.log(graph.hasVertex('Y')); // false;
3069
+ * console.log(graph.size); // 2;
3070
+ */
2393
3071
  deleteEdge(edgeOrSrcVertexKey, destVertexKey) {
2394
3072
  let removed = void 0;
2395
3073
  let src, dest;
@@ -2416,6 +3094,26 @@ var DirectedGraph = class _DirectedGraph extends AbstractGraph {
2416
3094
  }
2417
3095
  return removed;
2418
3096
  }
3097
+ /**
3098
+ * Remove a vertex
3099
+
3100
+
3101
+
3102
+
3103
+
3104
+
3105
+
3106
+
3107
+ * @example
3108
+ * // Remove a vertex
3109
+ * const g = new DirectedGraph();
3110
+ * g.addVertex('A');
3111
+ * g.addVertex('B');
3112
+ * g.addEdge('A', 'B');
3113
+ * g.deleteVertex('A');
3114
+ * console.log(g.hasVertex('A')); // false;
3115
+ * console.log(g.hasEdge('A', 'B')); // false;
3116
+ */
2419
3117
  deleteVertex(vertexOrKey) {
2420
3118
  let vertexKey;
2421
3119
  let vertex;
@@ -2447,11 +3145,28 @@ var DirectedGraph = class _DirectedGraph extends AbstractGraph {
2447
3145
  return removed;
2448
3146
  }
2449
3147
  /**
2450
- * Incoming edges of a vertex.
2451
- * @param vertexOrKey - Vertex or key.
2452
- * @returns Array of incoming edges.
2453
- * @remarks Time O(deg_in), Space O(deg_in)
2454
- */
3148
+ * Incoming edges of a vertex.
3149
+ * @param vertexOrKey - Vertex or key.
3150
+ * @returns Array of incoming edges.
3151
+ * @remarks Time O(deg_in), Space O(deg_in)
3152
+
3153
+
3154
+
3155
+
3156
+
3157
+
3158
+
3159
+
3160
+ * @example
3161
+ * // Get incoming edges
3162
+ * const g = new DirectedGraph();
3163
+ * g.addVertex('A');
3164
+ * g.addVertex('B');
3165
+ * g.addVertex('C');
3166
+ * g.addEdge('A', 'C');
3167
+ * g.addEdge('B', 'C');
3168
+ * console.log(g.incomingEdgesOf('C').length); // 2;
3169
+ */
2455
3170
  incomingEdgesOf(vertexOrKey) {
2456
3171
  const target = this._getVertex(vertexOrKey);
2457
3172
  if (target) {
@@ -2460,11 +3175,28 @@ var DirectedGraph = class _DirectedGraph extends AbstractGraph {
2460
3175
  return [];
2461
3176
  }
2462
3177
  /**
2463
- * Outgoing edges of a vertex.
2464
- * @param vertexOrKey - Vertex or key.
2465
- * @returns Array of outgoing edges.
2466
- * @remarks Time O(deg_out), Space O(deg_out)
2467
- */
3178
+ * Outgoing edges of a vertex.
3179
+ * @param vertexOrKey - Vertex or key.
3180
+ * @returns Array of outgoing edges.
3181
+ * @remarks Time O(deg_out), Space O(deg_out)
3182
+
3183
+
3184
+
3185
+
3186
+
3187
+
3188
+
3189
+
3190
+ * @example
3191
+ * // Get outgoing edges
3192
+ * const g = new DirectedGraph();
3193
+ * g.addVertex('A');
3194
+ * g.addVertex('B');
3195
+ * g.addVertex('C');
3196
+ * g.addEdge('A', 'B');
3197
+ * g.addEdge('A', 'C');
3198
+ * console.log(g.outgoingEdgesOf('A').length); // 2;
3199
+ */
2468
3200
  outgoingEdgesOf(vertexOrKey) {
2469
3201
  const target = this._getVertex(vertexOrKey);
2470
3202
  if (target) {
@@ -2523,11 +3255,44 @@ var DirectedGraph = class _DirectedGraph extends AbstractGraph {
2523
3255
  return destinations;
2524
3256
  }
2525
3257
  /**
2526
- * Topological sort if DAG; returns `undefined` if a cycle exists.
2527
- * @param propertyName - `'key'` to map to keys; `'vertex'` to keep instances.
2528
- * @returns Array of keys/vertices, or `undefined` when cycle is found.
2529
- * @remarks Time O(V + E), Space O(V)
2530
- */
3258
+ * Topological sort if DAG; returns `undefined` if a cycle exists.
3259
+ * @param propertyName - `'key'` to map to keys; `'vertex'` to keep instances.
3260
+ * @returns Array of keys/vertices, or `undefined` when cycle is found.
3261
+ * @remarks Time O(V + E), Space O(V)
3262
+
3263
+
3264
+
3265
+
3266
+
3267
+
3268
+
3269
+
3270
+
3271
+
3272
+
3273
+ * @example
3274
+ * // DirectedGraph topologicalSort for task scheduling
3275
+ * const graph = new DirectedGraph<string>();
3276
+ *
3277
+ * // Build a DAG (Directed Acyclic Graph) for task dependencies
3278
+ * graph.addVertex('Design');
3279
+ * graph.addVertex('Implement');
3280
+ * graph.addVertex('Test');
3281
+ * graph.addVertex('Deploy');
3282
+ *
3283
+ * // Add dependency edges
3284
+ * graph.addEdge('Design', 'Implement', 1); // Design must come before Implement
3285
+ * graph.addEdge('Implement', 'Test', 1); // Implement must come before Test
3286
+ * graph.addEdge('Test', 'Deploy', 1); // Test must come before Deploy
3287
+ *
3288
+ * // Topological sort gives valid execution order
3289
+ * const executionOrder = graph.topologicalSort();
3290
+ * console.log(executionOrder); // defined;
3291
+ * console.log(executionOrder); // ['Design', 'Implement', 'Test', 'Deploy'];
3292
+ *
3293
+ * // All vertices should be included
3294
+ * console.log(executionOrder?.length); // 4;
3295
+ */
2531
3296
  topologicalSort(propertyName) {
2532
3297
  propertyName = propertyName ?? "key";
2533
3298
  const statusMap = /* @__PURE__ */ new Map();
@@ -2559,6 +3324,24 @@ var DirectedGraph = class _DirectedGraph extends AbstractGraph {
2559
3324
  if (propertyName === "key") sorted = sorted.map((vertex) => vertex instanceof DirectedVertex ? vertex.key : vertex);
2560
3325
  return sorted.reverse();
2561
3326
  }
3327
+ /**
3328
+ * Get all edges
3329
+
3330
+
3331
+
3332
+
3333
+
3334
+
3335
+
3336
+
3337
+ * @example
3338
+ * // Get all edges
3339
+ * const g = new DirectedGraph();
3340
+ * g.addVertex('A');
3341
+ * g.addVertex('B');
3342
+ * g.addEdge('A', 'B', 3);
3343
+ * console.log(g.edgeSet().length); // 1;
3344
+ */
2562
3345
  edgeSet() {
2563
3346
  let edgeMap = [];
2564
3347
  this._outEdgeMap.forEach((outEdges) => {
@@ -2566,6 +3349,28 @@ var DirectedGraph = class _DirectedGraph extends AbstractGraph {
2566
3349
  });
2567
3350
  return edgeMap;
2568
3351
  }
3352
+ /**
3353
+ * Get outgoing neighbors
3354
+
3355
+
3356
+
3357
+
3358
+
3359
+
3360
+
3361
+
3362
+
3363
+ * @example
3364
+ * // Get outgoing neighbors
3365
+ * const g = new DirectedGraph();
3366
+ * g.addVertex('A');
3367
+ * g.addVertex('B');
3368
+ * g.addVertex('C');
3369
+ * g.addEdge('A', 'B');
3370
+ * g.addEdge('A', 'C');
3371
+ * const neighbors = g.getNeighbors('A');
3372
+ * console.log(neighbors.map(v => v.key).sort()); // ['B', 'C'];
3373
+ */
2569
3374
  getNeighbors(vertexOrKey) {
2570
3375
  const neighbors = [];
2571
3376
  const vertex = this._getVertex(vertexOrKey);
@@ -2623,10 +3428,31 @@ var DirectedGraph = class _DirectedGraph extends AbstractGraph {
2623
3428
  return super.clone();
2624
3429
  }
2625
3430
  /**
2626
- * Tarjan's algorithm for strongly connected components.
2627
- * @returns `{ dfnMap, lowMap, SCCs }`.
2628
- * @remarks Time O(V + E), Space O(V + E)
2629
- */
3431
+ * Tarjan's algorithm for strongly connected components.
3432
+ * @returns `{ dfnMap, lowMap, SCCs }`.
3433
+ * @remarks Time O(V + E), Space O(V + E)
3434
+
3435
+
3436
+
3437
+
3438
+
3439
+
3440
+
3441
+
3442
+ * @example
3443
+ * // Find strongly connected components
3444
+ * const g = new DirectedGraph();
3445
+ * g.addVertex('A');
3446
+ * g.addVertex('B');
3447
+ * g.addVertex('C');
3448
+ * g.addEdge('A', 'B');
3449
+ * g.addEdge('B', 'C');
3450
+ * g.addEdge('C', 'A');
3451
+ * const { SCCs } = g.tarjan();
3452
+ * // A→B→C→A forms one SCC with 3 members
3453
+ * const sccArrays = [...SCCs.values()];
3454
+ * console.log(sccArrays.some(scc => scc.length === 3)); // true;
3455
+ */
2630
3456
  tarjan() {
2631
3457
  const dfnMap = /* @__PURE__ */ new Map();
2632
3458
  const lowMap = /* @__PURE__ */ new Map();
@@ -2684,10 +3510,29 @@ var DirectedGraph = class _DirectedGraph extends AbstractGraph {
2684
3510
  return this.tarjan().lowMap;
2685
3511
  }
2686
3512
  /**
2687
- * Strongly connected components computed by `tarjan()`.
2688
- * @returns Map from SCC id to vertices.
2689
- * @remarks Time O(#SCC + V), Space O(V)
2690
- */
3513
+ * Strongly connected components computed by `tarjan()`.
3514
+ * @returns Map from SCC id to vertices.
3515
+ * @remarks Time O(#SCC + V), Space O(V)
3516
+
3517
+
3518
+
3519
+
3520
+
3521
+
3522
+
3523
+
3524
+ * @example
3525
+ * // Get strongly connected components
3526
+ * const g = new DirectedGraph();
3527
+ * g.addVertex(1);
3528
+ * g.addVertex(2);
3529
+ * g.addVertex(3);
3530
+ * g.addEdge(1, 2);
3531
+ * g.addEdge(2, 3);
3532
+ * g.addEdge(3, 1);
3533
+ * const sccs = g.getSCCs(); // Map<number, VO[]>
3534
+ * console.log(sccs.size); // >= 1;
3535
+ */
2691
3536
  getSCCs() {
2692
3537
  return this.tarjan().SCCs;
2693
3538
  }
@@ -2811,12 +3656,27 @@ var UndirectedGraph = class _UndirectedGraph extends AbstractGraph {
2811
3656
  return new UndirectedEdge(v1, v2, weight ?? this.options.defaultEdgeWeight ?? 1, value);
2812
3657
  }
2813
3658
  /**
2814
- * Get an undirected edge between two vertices, if present.
2815
- * @param v1 - One vertex or key.
2816
- * @param v2 - The other vertex or key.
2817
- * @returns Edge instance or `undefined`.
2818
- * @remarks Time O(1) avg, Space O(1)
2819
- */
3659
+ * Get an undirected edge between two vertices, if present.
3660
+ * @param v1 - One vertex or key.
3661
+ * @param v2 - The other vertex or key.
3662
+ * @returns Edge instance or `undefined`.
3663
+ * @remarks Time O(1) avg, Space O(1)
3664
+
3665
+
3666
+
3667
+
3668
+
3669
+
3670
+
3671
+
3672
+ * @example
3673
+ * // Get edge between vertices
3674
+ * const g = new UndirectedGraph();
3675
+ * g.addVertex('A');
3676
+ * g.addVertex('B');
3677
+ * g.addEdge('A', 'B', 7);
3678
+ * console.log(g.getEdge('A', 'B')?.weight); // 7;
3679
+ */
2820
3680
  getEdge(v1, v2) {
2821
3681
  let edgeMap = [];
2822
3682
  if (v1 !== void 0 && v2 !== void 0) {
@@ -2853,12 +3713,50 @@ var UndirectedGraph = class _UndirectedGraph extends AbstractGraph {
2853
3713
  return removed;
2854
3714
  }
2855
3715
  /**
2856
- * Delete an edge by instance or by a pair of keys.
2857
- * @param edgeOrOneSideVertexKey - Edge instance or one endpoint vertex/key.
2858
- * @param otherSideVertexKey - Required second endpoint when deleting by pair.
2859
- * @returns Removed edge or `undefined`.
2860
- * @remarks Time O(1) avg, Space O(1)
2861
- */
3716
+ * Delete an edge by instance or by a pair of keys.
3717
+ * @param edgeOrOneSideVertexKey - Edge instance or one endpoint vertex/key.
3718
+ * @param otherSideVertexKey - Required second endpoint when deleting by pair.
3719
+ * @returns Removed edge or `undefined`.
3720
+ * @remarks Time O(1) avg, Space O(1)
3721
+
3722
+
3723
+
3724
+
3725
+
3726
+
3727
+
3728
+
3729
+
3730
+
3731
+
3732
+ * @example
3733
+ * // UndirectedGraph deleteEdge and vertex operations
3734
+ * const graph = new UndirectedGraph<string>();
3735
+ *
3736
+ * // Build a simple undirected graph
3737
+ * graph.addVertex('X');
3738
+ * graph.addVertex('Y');
3739
+ * graph.addVertex('Z');
3740
+ * graph.addEdge('X', 'Y', 1);
3741
+ * graph.addEdge('Y', 'Z', 2);
3742
+ * graph.addEdge('X', 'Z', 3);
3743
+ *
3744
+ * // Delete an edge
3745
+ * graph.deleteEdge('X', 'Y');
3746
+ * console.log(graph.hasEdge('X', 'Y')); // false;
3747
+ *
3748
+ * // Bidirectional deletion confirmed
3749
+ * console.log(graph.hasEdge('Y', 'X')); // false;
3750
+ *
3751
+ * // Other edges should remain
3752
+ * console.log(graph.hasEdge('Y', 'Z')); // true;
3753
+ * console.log(graph.hasEdge('Z', 'Y')); // true;
3754
+ *
3755
+ * // Delete a vertex
3756
+ * graph.deleteVertex('Y');
3757
+ * console.log(graph.hasVertex('Y')); // false;
3758
+ * console.log(graph.size); // 2;
3759
+ */
2862
3760
  deleteEdge(edgeOrOneSideVertexKey, otherSideVertexKey) {
2863
3761
  let oneSide, otherSide;
2864
3762
  if (this.isVertexKey(edgeOrOneSideVertexKey)) {
@@ -2879,11 +3777,27 @@ var UndirectedGraph = class _UndirectedGraph extends AbstractGraph {
2879
3777
  }
2880
3778
  }
2881
3779
  /**
2882
- * Delete a vertex and remove it from all neighbor lists.
2883
- * @param vertexOrKey - Vertex or key.
2884
- * @returns `true` if removed; otherwise `false`.
2885
- * @remarks Time O(deg), Space O(1)
2886
- */
3780
+ * Delete a vertex and remove it from all neighbor lists.
3781
+ * @param vertexOrKey - Vertex or key.
3782
+ * @returns `true` if removed; otherwise `false`.
3783
+ * @remarks Time O(deg), Space O(1)
3784
+
3785
+
3786
+
3787
+
3788
+
3789
+
3790
+
3791
+
3792
+ * @example
3793
+ * // Remove vertex and edges
3794
+ * const g = new UndirectedGraph();
3795
+ * g.addVertex('A');
3796
+ * g.addVertex('B');
3797
+ * g.addEdge('A', 'B');
3798
+ * g.deleteVertex('A');
3799
+ * console.log(g.hasVertex('A')); // false;
3800
+ */
2887
3801
  deleteVertex(vertexOrKey) {
2888
3802
  let vertexKey;
2889
3803
  let vertex;
@@ -2938,10 +3852,25 @@ var UndirectedGraph = class _UndirectedGraph extends AbstractGraph {
2938
3852
  }
2939
3853
  }
2940
3854
  /**
2941
- * Unique set of undirected edges across endpoints.
2942
- * @returns Array of edges.
2943
- * @remarks Time O(E), Space O(E)
2944
- */
3855
+ * Unique set of undirected edges across endpoints.
3856
+ * @returns Array of edges.
3857
+ * @remarks Time O(E), Space O(E)
3858
+
3859
+
3860
+
3861
+
3862
+
3863
+
3864
+
3865
+
3866
+ * @example
3867
+ * // Get all edges
3868
+ * const g = new UndirectedGraph();
3869
+ * g.addVertex('A');
3870
+ * g.addVertex('B');
3871
+ * g.addEdge('A', 'B');
3872
+ * console.log(g.edgeSet().length); // 1;
3873
+ */
2945
3874
  edgeSet() {
2946
3875
  const edgeSet = /* @__PURE__ */ new Set();
2947
3876
  this._edgeMap.forEach((edgeMap) => {
@@ -2951,6 +3880,52 @@ var UndirectedGraph = class _UndirectedGraph extends AbstractGraph {
2951
3880
  });
2952
3881
  return [...edgeSet];
2953
3882
  }
3883
+ /**
3884
+ * UndirectedGraph connectivity and neighbors
3885
+
3886
+
3887
+
3888
+
3889
+
3890
+
3891
+
3892
+
3893
+
3894
+
3895
+
3896
+ * @example
3897
+ * // UndirectedGraph connectivity and neighbors
3898
+ * const graph = new UndirectedGraph<string>();
3899
+ *
3900
+ * // Build a friendship network
3901
+ * const people = ['Alice', 'Bob', 'Charlie', 'Diana', 'Eve'];
3902
+ * for (const person of people) {
3903
+ * graph.addVertex(person);
3904
+ * }
3905
+ *
3906
+ * // Add friendships (undirected edges)
3907
+ * graph.addEdge('Alice', 'Bob', 1);
3908
+ * graph.addEdge('Alice', 'Charlie', 1);
3909
+ * graph.addEdge('Bob', 'Diana', 1);
3910
+ * graph.addEdge('Charlie', 'Eve', 1);
3911
+ * graph.addEdge('Diana', 'Eve', 1);
3912
+ *
3913
+ * // Get friends of each person
3914
+ * const aliceFriends = graph.getNeighbors('Alice');
3915
+ * console.log(aliceFriends[0].key); // 'Bob';
3916
+ * console.log(aliceFriends[1].key); // 'Charlie';
3917
+ * console.log(aliceFriends.length); // 2;
3918
+ *
3919
+ * const dianaFriends = graph.getNeighbors('Diana');
3920
+ * console.log(dianaFriends[0].key); // 'Bob';
3921
+ * console.log(dianaFriends[1].key); // 'Eve';
3922
+ * console.log(dianaFriends.length); // 2;
3923
+ *
3924
+ * // Verify bidirectional friendship
3925
+ * const bobFriends = graph.getNeighbors('Bob');
3926
+ * console.log(bobFriends[0].key); // 'Alice'; // Alice -> Bob -> Alice ✓
3927
+ * console.log(bobFriends[1].key); // 'Diana';
3928
+ */
2954
3929
  getNeighbors(vertexOrKey) {
2955
3930
  const neighbors = [];
2956
3931
  const vertex = this._getVertex(vertexOrKey);
@@ -3007,10 +3982,28 @@ var UndirectedGraph = class _UndirectedGraph extends AbstractGraph {
3007
3982
  return super.clone();
3008
3983
  }
3009
3984
  /**
3010
- * Tarjan-based bridge and articulation point detection.
3011
- * @returns `{ dfnMap, lowMap, bridges, cutVertices }`.
3012
- * @remarks Time O(V + E), Space O(V + E)
3013
- */
3985
+ * Tarjan-based bridge and articulation point detection.
3986
+ * @returns `{ dfnMap, lowMap, bridges, cutVertices }`.
3987
+ * @remarks Time O(V + E), Space O(V + E)
3988
+
3989
+
3990
+
3991
+
3992
+
3993
+
3994
+
3995
+
3996
+ * @example
3997
+ * // Find articulation points and bridges
3998
+ * const g = new UndirectedGraph();
3999
+ * g.addVertex('A');
4000
+ * g.addVertex('B');
4001
+ * g.addVertex('C');
4002
+ * g.addEdge('A', 'B');
4003
+ * g.addEdge('B', 'C');
4004
+ * const result = g.tarjan();
4005
+ * console.log(result); // defined;
4006
+ */
3014
4007
  tarjan() {
3015
4008
  const dfnMap = /* @__PURE__ */ new Map();
3016
4009
  const lowMap = /* @__PURE__ */ new Map();
@@ -3058,18 +4051,152 @@ var UndirectedGraph = class _UndirectedGraph extends AbstractGraph {
3058
4051
  };
3059
4052
  }
3060
4053
  /**
3061
- * Get bridges discovered by `tarjan()`.
3062
- * @returns Array of edges that are bridges.
3063
- * @remarks Time O(B), Space O(1)
4054
+ * Find biconnected components using edge-stack Tarjan variant.
4055
+ * A biconnected component is a maximal biconnected subgraph.
4056
+ * @returns Array of edge arrays, each representing a biconnected component.
4057
+ * @remarks Time O(V + E), Space O(V + E)
3064
4058
  */
4059
+ getBiconnectedComponents() {
4060
+ const dfn = /* @__PURE__ */ new Map();
4061
+ const low = /* @__PURE__ */ new Map();
4062
+ const edgeStack = [];
4063
+ const components = [];
4064
+ let time = 0;
4065
+ const dfs = /* @__PURE__ */ __name((vertex, parent) => {
4066
+ dfn.set(vertex, time);
4067
+ low.set(vertex, time);
4068
+ time++;
4069
+ const neighbors = this.getNeighbors(vertex);
4070
+ let childCount = 0;
4071
+ for (const neighbor of neighbors) {
4072
+ const edge = this.getEdge(vertex, neighbor);
4073
+ if (!edge) continue;
4074
+ if (!dfn.has(neighbor)) {
4075
+ childCount++;
4076
+ edgeStack.push(edge);
4077
+ dfs(neighbor, vertex);
4078
+ low.set(vertex, Math.min(low.get(vertex), low.get(neighbor)));
4079
+ if (parent === void 0 && childCount > 1 || parent !== void 0 && low.get(neighbor) >= dfn.get(vertex)) {
4080
+ const component = [];
4081
+ let e;
4082
+ do {
4083
+ e = edgeStack.pop();
4084
+ if (e) component.push(e);
4085
+ } while (e && e !== edge);
4086
+ if (component.length > 0) components.push(component);
4087
+ }
4088
+ } else if (neighbor !== parent && dfn.get(neighbor) < dfn.get(vertex)) {
4089
+ edgeStack.push(edge);
4090
+ low.set(vertex, Math.min(low.get(vertex), dfn.get(neighbor)));
4091
+ }
4092
+ }
4093
+ }, "dfs");
4094
+ for (const vertex of this.vertexMap.values()) {
4095
+ if (!dfn.has(vertex)) {
4096
+ dfs(vertex, void 0);
4097
+ if (edgeStack.length > 0) {
4098
+ components.push([...edgeStack]);
4099
+ edgeStack.length = 0;
4100
+ }
4101
+ }
4102
+ }
4103
+ return components;
4104
+ }
4105
+ /**
4106
+ * Detect whether the graph contains a cycle.
4107
+ * Uses DFS with parent tracking.
4108
+ * @returns `true` if a cycle exists, `false` otherwise.
4109
+ * @remarks Time O(V + E), Space O(V)
4110
+
4111
+
4112
+
4113
+
4114
+
4115
+
4116
+
4117
+
4118
+ * @example
4119
+ * // Detect cycle
4120
+ * const g = new UndirectedGraph();
4121
+ * g.addVertex('A');
4122
+ * g.addVertex('B');
4123
+ * g.addVertex('C');
4124
+ * g.addEdge('A', 'B');
4125
+ * g.addEdge('B', 'C');
4126
+ * console.log(g.hasCycle()); // false;
4127
+ * g.addEdge('C', 'A');
4128
+ * console.log(g.hasCycle()); // true;
4129
+ */
4130
+ hasCycle() {
4131
+ const visited = /* @__PURE__ */ new Set();
4132
+ const dfs = /* @__PURE__ */ __name((vertex, parent) => {
4133
+ visited.add(vertex);
4134
+ for (const neighbor of this.getNeighbors(vertex)) {
4135
+ if (!visited.has(neighbor)) {
4136
+ if (dfs(neighbor, vertex)) return true;
4137
+ } else if (neighbor !== parent) {
4138
+ return true;
4139
+ }
4140
+ }
4141
+ return false;
4142
+ }, "dfs");
4143
+ for (const vertex of this.vertexMap.values()) {
4144
+ if (!visited.has(vertex)) {
4145
+ if (dfs(vertex, void 0)) return true;
4146
+ }
4147
+ }
4148
+ return false;
4149
+ }
4150
+ /**
4151
+ * Get bridges discovered by `tarjan()`.
4152
+ * @returns Array of edges that are bridges.
4153
+ * @remarks Time O(B), Space O(1)
4154
+
4155
+
4156
+
4157
+
4158
+
4159
+
4160
+
4161
+
4162
+ * @example
4163
+ * // Find bridge edges
4164
+ * const g = new UndirectedGraph();
4165
+ * g.addVertex('A');
4166
+ * g.addVertex('B');
4167
+ * g.addVertex('C');
4168
+ * g.addEdge('A', 'B');
4169
+ * g.addEdge('B', 'C');
4170
+ * const bridges = g.getBridges();
4171
+ * console.log(bridges.length); // 2;
4172
+ */
3065
4173
  getBridges() {
3066
4174
  return this.tarjan().bridges;
3067
4175
  }
3068
4176
  /**
3069
- * Get articulation points discovered by `tarjan()`.
3070
- * @returns Array of cut vertices.
3071
- * @remarks Time O(C), Space O(1)
3072
- */
4177
+ * Get articulation points discovered by `tarjan()`.
4178
+ * @returns Array of cut vertices.
4179
+ * @remarks Time O(C), Space O(1)
4180
+
4181
+
4182
+
4183
+
4184
+
4185
+
4186
+
4187
+
4188
+ * @example
4189
+ * // Find articulation points
4190
+ * const g = new UndirectedGraph();
4191
+ * g.addVertex('A');
4192
+ * g.addVertex('B');
4193
+ * g.addVertex('C');
4194
+ * g.addEdge('A', 'B');
4195
+ * g.addEdge('B', 'C');
4196
+ * const cuts = g.getCutVertices();
4197
+ * console.log(cuts.length); // 1;
4198
+ * console.log(cuts[0].key); // 'B';
4199
+ */
3073
4200
  getCutVertices() {
3074
4201
  return this.tarjan().cutVertices;
3075
4202
  }
@@ -3209,30 +4336,6 @@ var MapGraph = class _MapGraph extends DirectedGraph {
3209
4336
  return new _MapGraph(oc, br);
3210
4337
  }
3211
4338
  };
3212
-
3213
- // src/common/index.ts
3214
- var DFSOperation = /* @__PURE__ */ ((DFSOperation2) => {
3215
- DFSOperation2[DFSOperation2["VISIT"] = 0] = "VISIT";
3216
- DFSOperation2[DFSOperation2["PROCESS"] = 1] = "PROCESS";
3217
- return DFSOperation2;
3218
- })(DFSOperation || {});
3219
- var Range = class {
3220
- constructor(low, high, includeLow = true, includeHigh = true) {
3221
- this.low = low;
3222
- this.high = high;
3223
- this.includeLow = includeLow;
3224
- this.includeHigh = includeHigh;
3225
- }
3226
- static {
3227
- __name(this, "Range");
3228
- }
3229
- // Determine whether a key is within the range
3230
- isInRange(key, comparator) {
3231
- const lowCheck = this.includeLow ? comparator(key, this.low) >= 0 : comparator(key, this.low) > 0;
3232
- const highCheck = this.includeHigh ? comparator(key, this.high) <= 0 : comparator(key, this.high) < 0;
3233
- return lowCheck && highCheck;
3234
- }
3235
- };
3236
4339
  /**
3237
4340
  * data-structure-typed
3238
4341
  *
@@ -3248,6 +4351,7 @@ exports.DFSOperation = DFSOperation;
3248
4351
  exports.DirectedEdge = DirectedEdge;
3249
4352
  exports.DirectedGraph = DirectedGraph;
3250
4353
  exports.DirectedVertex = DirectedVertex;
4354
+ exports.ERR = ERR;
3251
4355
  exports.MapEdge = MapEdge;
3252
4356
  exports.MapGraph = MapGraph;
3253
4357
  exports.MapVertex = MapVertex;