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