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.
- package/dist/cjs/index.cjs +1324 -220
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/cjs-legacy/index.cjs +1325 -219
- package/dist/cjs-legacy/index.cjs.map +1 -1
- package/dist/esm/index.mjs +1324 -221
- package/dist/esm/index.mjs.map +1 -1
- package/dist/esm-legacy/index.mjs +1325 -220
- package/dist/esm-legacy/index.mjs.map +1 -1
- package/dist/types/common/error.d.ts +23 -0
- package/dist/types/common/index.d.ts +1 -0
- package/dist/types/data-structures/base/iterable-element-base.d.ts +1 -1
- package/dist/types/data-structures/binary-tree/avl-tree.d.ts +128 -51
- package/dist/types/data-structures/binary-tree/binary-indexed-tree.d.ts +210 -164
- package/dist/types/data-structures/binary-tree/binary-tree.d.ts +439 -78
- package/dist/types/data-structures/binary-tree/bst.d.ts +311 -28
- package/dist/types/data-structures/binary-tree/red-black-tree.d.ts +217 -31
- package/dist/types/data-structures/binary-tree/segment-tree.d.ts +218 -152
- package/dist/types/data-structures/binary-tree/tree-map.d.ts +1281 -5
- package/dist/types/data-structures/binary-tree/tree-multi-map.d.ts +1087 -201
- package/dist/types/data-structures/binary-tree/tree-multi-set.d.ts +858 -65
- package/dist/types/data-structures/binary-tree/tree-set.d.ts +1133 -5
- package/dist/types/data-structures/graph/abstract-graph.d.ts +44 -0
- package/dist/types/data-structures/graph/directed-graph.d.ts +220 -47
- package/dist/types/data-structures/graph/map-graph.d.ts +59 -1
- package/dist/types/data-structures/graph/undirected-graph.d.ts +218 -59
- package/dist/types/data-structures/hash/hash-map.d.ts +230 -77
- package/dist/types/data-structures/heap/heap.d.ts +287 -99
- package/dist/types/data-structures/heap/max-heap.d.ts +46 -0
- package/dist/types/data-structures/heap/min-heap.d.ts +59 -0
- package/dist/types/data-structures/linked-list/doubly-linked-list.d.ts +286 -44
- package/dist/types/data-structures/linked-list/singly-linked-list.d.ts +278 -65
- package/dist/types/data-structures/linked-list/skip-linked-list.d.ts +415 -12
- package/dist/types/data-structures/matrix/matrix.d.ts +331 -0
- package/dist/types/data-structures/priority-queue/max-priority-queue.d.ts +57 -0
- package/dist/types/data-structures/priority-queue/min-priority-queue.d.ts +60 -0
- package/dist/types/data-structures/priority-queue/priority-queue.d.ts +60 -0
- package/dist/types/data-structures/queue/deque.d.ts +313 -66
- package/dist/types/data-structures/queue/queue.d.ts +211 -42
- package/dist/types/data-structures/stack/stack.d.ts +174 -32
- package/dist/types/data-structures/trie/trie.d.ts +213 -43
- package/dist/types/types/data-structures/binary-tree/segment-tree.d.ts +1 -1
- package/dist/types/types/data-structures/linked-list/skip-linked-list.d.ts +1 -4
- package/dist/types/types/data-structures/queue/deque.d.ts +6 -0
- package/dist/umd/graph-typed.js +1323 -217
- package/dist/umd/graph-typed.js.map +1 -1
- package/dist/umd/graph-typed.min.js +3 -1
- package/dist/umd/graph-typed.min.js.map +1 -1
- package/package.json +2 -2
- package/src/common/error.ts +60 -0
- package/src/common/index.ts +2 -0
- package/src/data-structures/base/iterable-element-base.ts +2 -2
- package/src/data-structures/binary-tree/avl-tree.ts +134 -51
- package/src/data-structures/binary-tree/binary-indexed-tree.ts +303 -247
- package/src/data-structures/binary-tree/binary-tree.ts +542 -121
- package/src/data-structures/binary-tree/bst.ts +346 -37
- package/src/data-structures/binary-tree/red-black-tree.ts +309 -96
- package/src/data-structures/binary-tree/segment-tree.ts +372 -248
- package/src/data-structures/binary-tree/tree-map.ts +1292 -13
- package/src/data-structures/binary-tree/tree-multi-map.ts +1098 -215
- package/src/data-structures/binary-tree/tree-multi-set.ts +863 -69
- package/src/data-structures/binary-tree/tree-set.ts +1143 -15
- package/src/data-structures/graph/abstract-graph.ts +106 -1
- package/src/data-structures/graph/directed-graph.ts +223 -47
- package/src/data-structures/graph/map-graph.ts +59 -1
- package/src/data-structures/graph/undirected-graph.ts +299 -59
- package/src/data-structures/hash/hash-map.ts +243 -79
- package/src/data-structures/heap/heap.ts +291 -102
- package/src/data-structures/heap/max-heap.ts +48 -3
- package/src/data-structures/heap/min-heap.ts +59 -0
- package/src/data-structures/linked-list/doubly-linked-list.ts +286 -44
- package/src/data-structures/linked-list/singly-linked-list.ts +278 -65
- package/src/data-structures/linked-list/skip-linked-list.ts +689 -90
- package/src/data-structures/matrix/matrix.ts +425 -22
- package/src/data-structures/priority-queue/max-priority-queue.ts +59 -3
- package/src/data-structures/priority-queue/min-priority-queue.ts +60 -0
- package/src/data-structures/priority-queue/priority-queue.ts +60 -0
- package/src/data-structures/queue/deque.ts +343 -68
- package/src/data-structures/queue/queue.ts +211 -42
- package/src/data-structures/stack/stack.ts +174 -32
- package/src/data-structures/trie/trie.ts +215 -44
- package/src/types/data-structures/binary-tree/segment-tree.ts +1 -1
- package/src/types/data-structures/linked-list/skip-linked-list.ts +2 -1
- package/src/types/data-structures/queue/deque.ts +7 -0
- package/src/utils/utils.ts +4 -2
package/dist/umd/graph-typed.js
CHANGED
|
@@ -30,6 +30,7 @@ var graphTyped = (() => {
|
|
|
30
30
|
DirectedEdge: () => DirectedEdge,
|
|
31
31
|
DirectedGraph: () => DirectedGraph,
|
|
32
32
|
DirectedVertex: () => DirectedVertex,
|
|
33
|
+
ERR: () => ERR,
|
|
33
34
|
MapEdge: () => MapEdge,
|
|
34
35
|
MapGraph: () => MapGraph,
|
|
35
36
|
MapVertex: () => MapVertex,
|
|
@@ -60,6 +61,52 @@ var graphTyped = (() => {
|
|
|
60
61
|
return result;
|
|
61
62
|
};
|
|
62
63
|
|
|
64
|
+
// src/common/error.ts
|
|
65
|
+
var ERR = {
|
|
66
|
+
// Range / index
|
|
67
|
+
indexOutOfRange: (index, min, max, ctx) => `${ctx ? ctx + ": " : ""}Index ${index} is out of range [${min}, ${max}].`,
|
|
68
|
+
invalidIndex: (ctx) => `${ctx ? ctx + ": " : ""}Index must be an integer.`,
|
|
69
|
+
// Type / argument
|
|
70
|
+
invalidArgument: (reason, ctx) => `${ctx ? ctx + ": " : ""}${reason}`,
|
|
71
|
+
comparatorRequired: (ctx) => `${ctx ? ctx + ": " : ""}Comparator is required for non-number/non-string/non-Date keys.`,
|
|
72
|
+
invalidKey: (reason, ctx) => `${ctx ? ctx + ": " : ""}${reason}`,
|
|
73
|
+
notAFunction: (name, ctx) => `${ctx ? ctx + ": " : ""}${name} must be a function.`,
|
|
74
|
+
invalidEntry: (ctx) => `${ctx ? ctx + ": " : ""}Each entry must be a [key, value] tuple.`,
|
|
75
|
+
invalidNaN: (ctx) => `${ctx ? ctx + ": " : ""}NaN is not a valid key.`,
|
|
76
|
+
invalidDate: (ctx) => `${ctx ? ctx + ": " : ""}Invalid Date key.`,
|
|
77
|
+
reduceEmpty: (ctx) => `${ctx ? ctx + ": " : ""}Reduce of empty structure with no initial value.`,
|
|
78
|
+
callbackReturnType: (expected, got, ctx) => `${ctx ? ctx + ": " : ""}Callback must return ${expected}; got ${got}.`,
|
|
79
|
+
// State / operation
|
|
80
|
+
invalidOperation: (reason, ctx) => `${ctx ? ctx + ": " : ""}${reason}`,
|
|
81
|
+
// Matrix
|
|
82
|
+
matrixDimensionMismatch: (op) => `Matrix: Dimensions must be compatible for ${op}.`,
|
|
83
|
+
matrixSingular: () => "Matrix: Singular matrix, inverse does not exist.",
|
|
84
|
+
matrixNotSquare: () => "Matrix: Must be square for inversion.",
|
|
85
|
+
matrixNotRectangular: () => "Matrix: Must be rectangular for transposition.",
|
|
86
|
+
matrixRowMismatch: (expected, got) => `Matrix: Expected row length ${expected}, but got ${got}.`
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
// src/common/index.ts
|
|
90
|
+
var DFSOperation = /* @__PURE__ */ ((DFSOperation2) => {
|
|
91
|
+
DFSOperation2[DFSOperation2["VISIT"] = 0] = "VISIT";
|
|
92
|
+
DFSOperation2[DFSOperation2["PROCESS"] = 1] = "PROCESS";
|
|
93
|
+
return DFSOperation2;
|
|
94
|
+
})(DFSOperation || {});
|
|
95
|
+
var Range = class {
|
|
96
|
+
constructor(low, high, includeLow = true, includeHigh = true) {
|
|
97
|
+
this.low = low;
|
|
98
|
+
this.high = high;
|
|
99
|
+
this.includeLow = includeLow;
|
|
100
|
+
this.includeHigh = includeHigh;
|
|
101
|
+
}
|
|
102
|
+
// Determine whether a key is within the range
|
|
103
|
+
isInRange(key, comparator) {
|
|
104
|
+
const lowCheck = this.includeLow ? comparator(key, this.low) >= 0 : comparator(key, this.low) > 0;
|
|
105
|
+
const highCheck = this.includeHigh ? comparator(key, this.high) <= 0 : comparator(key, this.high) < 0;
|
|
106
|
+
return lowCheck && highCheck;
|
|
107
|
+
}
|
|
108
|
+
};
|
|
109
|
+
|
|
63
110
|
// src/data-structures/base/iterable-entry-base.ts
|
|
64
111
|
var IterableEntryBase = class {
|
|
65
112
|
/**
|
|
@@ -474,7 +521,7 @@ var graphTyped = (() => {
|
|
|
474
521
|
__publicField(this, "_elements", []);
|
|
475
522
|
__publicField(this, "_DEFAULT_COMPARATOR", (a, b) => {
|
|
476
523
|
if (typeof a === "object" || typeof b === "object") {
|
|
477
|
-
throw TypeError(
|
|
524
|
+
throw new TypeError(ERR.comparatorRequired("Heap"));
|
|
478
525
|
}
|
|
479
526
|
if (a > b) return 1;
|
|
480
527
|
if (a < b) return -1;
|
|
@@ -496,10 +543,30 @@ var graphTyped = (() => {
|
|
|
496
543
|
return this._elements;
|
|
497
544
|
}
|
|
498
545
|
/**
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
546
|
+
* Get the number of elements.
|
|
547
|
+
* @remarks Time O(1), Space O(1)
|
|
548
|
+
* @returns Heap size.
|
|
549
|
+
|
|
550
|
+
|
|
551
|
+
|
|
552
|
+
|
|
553
|
+
|
|
554
|
+
|
|
555
|
+
|
|
556
|
+
|
|
557
|
+
|
|
558
|
+
|
|
559
|
+
|
|
560
|
+
* @example
|
|
561
|
+
* // Track heap capacity
|
|
562
|
+
* const heap = new Heap<number>();
|
|
563
|
+
* console.log(heap.size); // 0;
|
|
564
|
+
* heap.add(10);
|
|
565
|
+
* heap.add(20);
|
|
566
|
+
* console.log(heap.size); // 2;
|
|
567
|
+
* heap.poll();
|
|
568
|
+
* console.log(heap.size); // 1;
|
|
569
|
+
*/
|
|
503
570
|
get size() {
|
|
504
571
|
return this.elements.length;
|
|
505
572
|
}
|
|
@@ -538,21 +605,61 @@ var graphTyped = (() => {
|
|
|
538
605
|
return new _Heap(elements, options);
|
|
539
606
|
}
|
|
540
607
|
/**
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
608
|
+
* Insert an element.
|
|
609
|
+
* @remarks Time O(1) amortized, Space O(1)
|
|
610
|
+
* @param element - Element to insert.
|
|
611
|
+
* @returns True.
|
|
612
|
+
|
|
613
|
+
|
|
614
|
+
|
|
615
|
+
|
|
616
|
+
|
|
617
|
+
|
|
618
|
+
|
|
619
|
+
|
|
620
|
+
|
|
621
|
+
|
|
622
|
+
|
|
623
|
+
* @example
|
|
624
|
+
* // basic Heap creation and add operation
|
|
625
|
+
* // Create a min heap (default)
|
|
626
|
+
* const minHeap = new Heap([5, 3, 7, 1, 9, 2]);
|
|
627
|
+
*
|
|
628
|
+
* // Verify size
|
|
629
|
+
* console.log(minHeap.size); // 6;
|
|
630
|
+
*
|
|
631
|
+
* // Add new element
|
|
632
|
+
* minHeap.add(4);
|
|
633
|
+
* console.log(minHeap.size); // 7;
|
|
634
|
+
*
|
|
635
|
+
* // Min heap property: smallest element at root
|
|
636
|
+
* const min = minHeap.peek();
|
|
637
|
+
* console.log(min); // 1;
|
|
638
|
+
*/
|
|
546
639
|
add(element) {
|
|
547
640
|
this._elements.push(element);
|
|
548
641
|
return this._bubbleUp(this.elements.length - 1);
|
|
549
642
|
}
|
|
550
643
|
/**
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
644
|
+
* Insert many elements from an iterable.
|
|
645
|
+
* @remarks Time O(N log N), Space O(1)
|
|
646
|
+
* @param elements - Iterable of elements or raw values.
|
|
647
|
+
* @returns Array of per-element success flags.
|
|
648
|
+
|
|
649
|
+
|
|
650
|
+
|
|
651
|
+
|
|
652
|
+
|
|
653
|
+
|
|
654
|
+
|
|
655
|
+
|
|
656
|
+
* @example
|
|
657
|
+
* // Add multiple elements
|
|
658
|
+
* const heap = new Heap<number>([], { comparator: (a, b) => a - b });
|
|
659
|
+
* heap.addMany([5, 3, 7, 1]);
|
|
660
|
+
* console.log(heap.peek()); // 1;
|
|
661
|
+
* console.log(heap.size); // 4;
|
|
662
|
+
*/
|
|
556
663
|
addMany(elements) {
|
|
557
664
|
const flags = [];
|
|
558
665
|
for (const el of elements) {
|
|
@@ -567,10 +674,46 @@ var graphTyped = (() => {
|
|
|
567
674
|
return flags;
|
|
568
675
|
}
|
|
569
676
|
/**
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
677
|
+
* Remove and return the top element.
|
|
678
|
+
* @remarks Time O(log N), Space O(1)
|
|
679
|
+
* @returns Top element or undefined.
|
|
680
|
+
|
|
681
|
+
|
|
682
|
+
|
|
683
|
+
|
|
684
|
+
|
|
685
|
+
|
|
686
|
+
|
|
687
|
+
|
|
688
|
+
|
|
689
|
+
|
|
690
|
+
|
|
691
|
+
* @example
|
|
692
|
+
* // Heap with custom comparator (MaxHeap behavior)
|
|
693
|
+
* interface Task {
|
|
694
|
+
* id: number;
|
|
695
|
+
* priority: number;
|
|
696
|
+
* name: string;
|
|
697
|
+
* }
|
|
698
|
+
*
|
|
699
|
+
* // Custom comparator for max heap behavior (higher priority first)
|
|
700
|
+
* const tasks: Task[] = [
|
|
701
|
+
* { id: 1, priority: 5, name: 'Email' },
|
|
702
|
+
* { id: 2, priority: 3, name: 'Chat' },
|
|
703
|
+
* { id: 3, priority: 8, name: 'Alert' }
|
|
704
|
+
* ];
|
|
705
|
+
*
|
|
706
|
+
* const maxHeap = new Heap(tasks, {
|
|
707
|
+
* comparator: (a: Task, b: Task) => b.priority - a.priority
|
|
708
|
+
* });
|
|
709
|
+
*
|
|
710
|
+
* console.log(maxHeap.size); // 3;
|
|
711
|
+
*
|
|
712
|
+
* // Peek returns highest priority task
|
|
713
|
+
* const topTask = maxHeap.peek();
|
|
714
|
+
* console.log(topTask?.priority); // 8;
|
|
715
|
+
* console.log(topTask?.name); // 'Alert';
|
|
716
|
+
*/
|
|
574
717
|
poll() {
|
|
575
718
|
if (this.elements.length === 0) return;
|
|
576
719
|
const value = this.elements[0];
|
|
@@ -582,26 +725,125 @@ var graphTyped = (() => {
|
|
|
582
725
|
return value;
|
|
583
726
|
}
|
|
584
727
|
/**
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
728
|
+
* Get the current top element without removing it.
|
|
729
|
+
* @remarks Time O(1), Space O(1)
|
|
730
|
+
* @returns Top element or undefined.
|
|
731
|
+
|
|
732
|
+
|
|
733
|
+
|
|
734
|
+
|
|
735
|
+
|
|
736
|
+
|
|
737
|
+
|
|
738
|
+
|
|
739
|
+
|
|
740
|
+
|
|
741
|
+
|
|
742
|
+
* @example
|
|
743
|
+
* // Heap for event processing with priority
|
|
744
|
+
* interface Event {
|
|
745
|
+
* id: number;
|
|
746
|
+
* type: 'critical' | 'warning' | 'info';
|
|
747
|
+
* timestamp: number;
|
|
748
|
+
* message: string;
|
|
749
|
+
* }
|
|
750
|
+
*
|
|
751
|
+
* // Custom priority: critical > warning > info
|
|
752
|
+
* const priorityMap = { critical: 3, warning: 2, info: 1 };
|
|
753
|
+
*
|
|
754
|
+
* const eventHeap = new Heap<Event>([], {
|
|
755
|
+
* comparator: (a: Event, b: Event) => {
|
|
756
|
+
* const priorityA = priorityMap[a.type];
|
|
757
|
+
* const priorityB = priorityMap[b.type];
|
|
758
|
+
* return priorityB - priorityA; // Higher priority first
|
|
759
|
+
* }
|
|
760
|
+
* });
|
|
761
|
+
*
|
|
762
|
+
* // Add events in random order
|
|
763
|
+
* eventHeap.add({ id: 1, type: 'info', timestamp: 100, message: 'User logged in' });
|
|
764
|
+
* eventHeap.add({ id: 2, type: 'critical', timestamp: 101, message: 'Server down' });
|
|
765
|
+
* eventHeap.add({ id: 3, type: 'warning', timestamp: 102, message: 'High memory' });
|
|
766
|
+
* eventHeap.add({ id: 4, type: 'info', timestamp: 103, message: 'Cache cleared' });
|
|
767
|
+
* eventHeap.add({ id: 5, type: 'critical', timestamp: 104, message: 'Database error' });
|
|
768
|
+
*
|
|
769
|
+
* console.log(eventHeap.size); // 5;
|
|
770
|
+
*
|
|
771
|
+
* // Process events by priority (critical first)
|
|
772
|
+
* const processedOrder: Event[] = [];
|
|
773
|
+
* while (eventHeap.size > 0) {
|
|
774
|
+
* const event = eventHeap.poll();
|
|
775
|
+
* if (event) {
|
|
776
|
+
* processedOrder.push(event);
|
|
777
|
+
* }
|
|
778
|
+
* }
|
|
779
|
+
*
|
|
780
|
+
* // Verify critical events came first
|
|
781
|
+
* console.log(processedOrder[0].type); // 'critical';
|
|
782
|
+
* console.log(processedOrder[1].type); // 'critical';
|
|
783
|
+
* console.log(processedOrder[2].type); // 'warning';
|
|
784
|
+
* console.log(processedOrder[3].type); // 'info';
|
|
785
|
+
* console.log(processedOrder[4].type); // 'info';
|
|
786
|
+
*
|
|
787
|
+
* // Verify O(log n) operations
|
|
788
|
+
* const newHeap = new Heap<number>([5, 3, 7, 1]);
|
|
789
|
+
*
|
|
790
|
+
* // Add - O(log n)
|
|
791
|
+
* newHeap.add(2);
|
|
792
|
+
* console.log(newHeap.size); // 5;
|
|
793
|
+
*
|
|
794
|
+
* // Poll - O(log n)
|
|
795
|
+
* const removed = newHeap.poll();
|
|
796
|
+
* console.log(removed); // 1;
|
|
797
|
+
*
|
|
798
|
+
* // Peek - O(1)
|
|
799
|
+
* const top = newHeap.peek();
|
|
800
|
+
* console.log(top); // 2;
|
|
801
|
+
*/
|
|
589
802
|
peek() {
|
|
590
803
|
return this.elements[0];
|
|
591
804
|
}
|
|
592
805
|
/**
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
806
|
+
* Check whether the heap is empty.
|
|
807
|
+
* @remarks Time O(1), Space O(1)
|
|
808
|
+
* @returns True if size is 0.
|
|
809
|
+
|
|
810
|
+
|
|
811
|
+
|
|
812
|
+
|
|
813
|
+
|
|
814
|
+
|
|
815
|
+
|
|
816
|
+
|
|
817
|
+
|
|
818
|
+
* @example
|
|
819
|
+
* // Check if heap is empty
|
|
820
|
+
* const heap = new Heap<number>([], { comparator: (a, b) => a - b });
|
|
821
|
+
* console.log(heap.isEmpty()); // true;
|
|
822
|
+
* heap.add(1);
|
|
823
|
+
* console.log(heap.isEmpty()); // false;
|
|
824
|
+
*/
|
|
597
825
|
isEmpty() {
|
|
598
826
|
return this.size === 0;
|
|
599
827
|
}
|
|
600
828
|
/**
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
829
|
+
* Remove all elements.
|
|
830
|
+
* @remarks Time O(1), Space O(1)
|
|
831
|
+
* @returns void
|
|
832
|
+
|
|
833
|
+
|
|
834
|
+
|
|
835
|
+
|
|
836
|
+
|
|
837
|
+
|
|
838
|
+
|
|
839
|
+
|
|
840
|
+
|
|
841
|
+
* @example
|
|
842
|
+
* // Remove all elements
|
|
843
|
+
* const heap = new Heap<number>([1, 2, 3], { comparator: (a, b) => a - b });
|
|
844
|
+
* heap.clear();
|
|
845
|
+
* console.log(heap.isEmpty()); // true;
|
|
846
|
+
*/
|
|
605
847
|
clear() {
|
|
606
848
|
this._elements = [];
|
|
607
849
|
}
|
|
@@ -616,21 +858,41 @@ var graphTyped = (() => {
|
|
|
616
858
|
return this.fix();
|
|
617
859
|
}
|
|
618
860
|
/**
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
861
|
+
* Check if an equal element exists in the heap.
|
|
862
|
+
* @remarks Time O(N), Space O(1)
|
|
863
|
+
* @param element - Element to search for.
|
|
864
|
+
* @returns True if found.
|
|
865
|
+
|
|
866
|
+
|
|
867
|
+
* @example
|
|
868
|
+
* // Check element existence
|
|
869
|
+
* const heap = new Heap<number>([3, 1, 2], { comparator: (a, b) => a - b });
|
|
870
|
+
* console.log(heap.has(1)); // true;
|
|
871
|
+
* console.log(heap.has(99)); // false;
|
|
872
|
+
*/
|
|
624
873
|
has(element) {
|
|
625
874
|
for (const el of this.elements) if (this._equals(el, element)) return true;
|
|
626
875
|
return false;
|
|
627
876
|
}
|
|
628
877
|
/**
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
878
|
+
* Delete one occurrence of an element.
|
|
879
|
+
* @remarks Time O(N), Space O(1)
|
|
880
|
+
* @param element - Element to delete.
|
|
881
|
+
* @returns True if an element was removed.
|
|
882
|
+
|
|
883
|
+
|
|
884
|
+
|
|
885
|
+
|
|
886
|
+
|
|
887
|
+
|
|
888
|
+
|
|
889
|
+
|
|
890
|
+
* @example
|
|
891
|
+
* // Remove specific element
|
|
892
|
+
* const heap = new Heap<number>([3, 1, 4, 1, 5], { comparator: (a, b) => a - b });
|
|
893
|
+
* heap.delete(4);
|
|
894
|
+
* console.log(heap.toArray().includes(4)); // false;
|
|
895
|
+
*/
|
|
634
896
|
delete(element) {
|
|
635
897
|
let index = -1;
|
|
636
898
|
for (let i = 0; i < this.elements.length; i++) {
|
|
@@ -688,11 +950,18 @@ var graphTyped = (() => {
|
|
|
688
950
|
return this;
|
|
689
951
|
}
|
|
690
952
|
/**
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
953
|
+
* Traverse the binary heap as a complete binary tree and collect elements.
|
|
954
|
+
* @remarks Time O(N), Space O(H)
|
|
955
|
+
* @param [order] - Traversal order: 'PRE' | 'IN' | 'POST'.
|
|
956
|
+
* @returns Array of visited elements.
|
|
957
|
+
|
|
958
|
+
|
|
959
|
+
* @example
|
|
960
|
+
* // Depth-first traversal
|
|
961
|
+
* const heap = new Heap<number>([3, 1, 2], { comparator: (a, b) => a - b });
|
|
962
|
+
* const result = heap.dfs('IN');
|
|
963
|
+
* console.log(result.length); // 3;
|
|
964
|
+
*/
|
|
696
965
|
dfs(order = "PRE") {
|
|
697
966
|
const result = [];
|
|
698
967
|
const _dfs = (index) => {
|
|
@@ -729,10 +998,26 @@ var graphTyped = (() => {
|
|
|
729
998
|
return results;
|
|
730
999
|
}
|
|
731
1000
|
/**
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
1001
|
+
* Return all elements in ascending order by repeatedly polling.
|
|
1002
|
+
* @remarks Time O(N log N), Space O(N)
|
|
1003
|
+
* @returns Sorted array of elements.
|
|
1004
|
+
|
|
1005
|
+
|
|
1006
|
+
|
|
1007
|
+
|
|
1008
|
+
|
|
1009
|
+
|
|
1010
|
+
|
|
1011
|
+
|
|
1012
|
+
|
|
1013
|
+
|
|
1014
|
+
|
|
1015
|
+
* @example
|
|
1016
|
+
* // Sort elements using heap
|
|
1017
|
+
* const heap = new Heap<number>([5, 1, 3, 2, 4]);
|
|
1018
|
+
* const sorted = heap.sort();
|
|
1019
|
+
* console.log(sorted); // [1, 2, 3, 4, 5];
|
|
1020
|
+
*/
|
|
736
1021
|
sort() {
|
|
737
1022
|
const visited = [];
|
|
738
1023
|
const cloned = this._createInstance();
|
|
@@ -744,22 +1029,52 @@ var graphTyped = (() => {
|
|
|
744
1029
|
return visited;
|
|
745
1030
|
}
|
|
746
1031
|
/**
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
1032
|
+
* Deep clone this heap.
|
|
1033
|
+
* @remarks Time O(N), Space O(N)
|
|
1034
|
+
* @returns A new heap with the same elements.
|
|
1035
|
+
|
|
1036
|
+
|
|
1037
|
+
|
|
1038
|
+
|
|
1039
|
+
|
|
1040
|
+
|
|
1041
|
+
|
|
1042
|
+
|
|
1043
|
+
|
|
1044
|
+
* @example
|
|
1045
|
+
* // Create independent copy
|
|
1046
|
+
* const heap = new Heap<number>([3, 1, 4], { comparator: (a, b) => a - b });
|
|
1047
|
+
* const copy = heap.clone();
|
|
1048
|
+
* copy.poll();
|
|
1049
|
+
* console.log(heap.size); // 3;
|
|
1050
|
+
* console.log(copy.size); // 2;
|
|
1051
|
+
*/
|
|
751
1052
|
clone() {
|
|
752
1053
|
const next = this._createInstance();
|
|
753
1054
|
for (const x of this.elements) next.add(x);
|
|
754
1055
|
return next;
|
|
755
1056
|
}
|
|
756
1057
|
/**
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
1058
|
+
* Filter elements into a new heap of the same class.
|
|
1059
|
+
* @remarks Time O(N log N), Space O(N)
|
|
1060
|
+
* @param callback - Predicate (element, index, heap) → boolean to keep element.
|
|
1061
|
+
* @param [thisArg] - Value for `this` inside the callback.
|
|
1062
|
+
* @returns A new heap with the kept elements.
|
|
1063
|
+
|
|
1064
|
+
|
|
1065
|
+
|
|
1066
|
+
|
|
1067
|
+
|
|
1068
|
+
|
|
1069
|
+
|
|
1070
|
+
|
|
1071
|
+
|
|
1072
|
+
* @example
|
|
1073
|
+
* // Filter elements
|
|
1074
|
+
* const heap = new Heap<number>([1, 2, 3, 4, 5], { comparator: (a, b) => a - b });
|
|
1075
|
+
* const evens = heap.filter(x => x % 2 === 0);
|
|
1076
|
+
* console.log(evens.size); // 2;
|
|
1077
|
+
*/
|
|
763
1078
|
filter(callback, thisArg) {
|
|
764
1079
|
const out = this._createInstance();
|
|
765
1080
|
let i = 0;
|
|
@@ -773,18 +1088,31 @@ var graphTyped = (() => {
|
|
|
773
1088
|
return out;
|
|
774
1089
|
}
|
|
775
1090
|
/**
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
1091
|
+
* Map elements into a new heap of possibly different element type.
|
|
1092
|
+
* @remarks Time O(N log N), Space O(N)
|
|
1093
|
+
* @template EM
|
|
1094
|
+
* @template RM
|
|
1095
|
+
* @param callback - Mapping function (element, index, heap) → newElement.
|
|
1096
|
+
* @param options - Options for the output heap, including comparator for EM.
|
|
1097
|
+
* @param [thisArg] - Value for `this` inside the callback.
|
|
1098
|
+
* @returns A new heap with mapped elements.
|
|
1099
|
+
|
|
1100
|
+
|
|
1101
|
+
|
|
1102
|
+
|
|
1103
|
+
|
|
1104
|
+
|
|
1105
|
+
|
|
1106
|
+
|
|
1107
|
+
* @example
|
|
1108
|
+
* // Transform elements
|
|
1109
|
+
* const heap = new Heap<number>([1, 2, 3], { comparator: (a, b) => a - b });
|
|
1110
|
+
* const doubled = heap.map(x => x * 2, { comparator: (a, b) => a - b });
|
|
1111
|
+
* console.log(doubled.peek()); // 2;
|
|
1112
|
+
*/
|
|
785
1113
|
map(callback, options, thisArg) {
|
|
786
1114
|
const { comparator, toElementFn, ...rest } = options != null ? options : {};
|
|
787
|
-
if (!comparator) throw new TypeError("Heap.map
|
|
1115
|
+
if (!comparator) throw new TypeError(ERR.comparatorRequired("Heap.map"));
|
|
788
1116
|
const out = this._createLike([], { ...rest, comparator, toElementFn });
|
|
789
1117
|
let i = 0;
|
|
790
1118
|
for (const x of this) {
|
|
@@ -1129,18 +1457,52 @@ var graphTyped = (() => {
|
|
|
1129
1457
|
this._autoCompactRatio = value;
|
|
1130
1458
|
}
|
|
1131
1459
|
/**
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1460
|
+
* Get the number of elements currently in the queue.
|
|
1461
|
+
* @remarks Time O(1), Space O(1)
|
|
1462
|
+
* @returns Current length.
|
|
1463
|
+
|
|
1464
|
+
|
|
1465
|
+
|
|
1466
|
+
|
|
1467
|
+
|
|
1468
|
+
|
|
1469
|
+
|
|
1470
|
+
|
|
1471
|
+
|
|
1472
|
+
|
|
1473
|
+
|
|
1474
|
+
* @example
|
|
1475
|
+
* // Track queue length
|
|
1476
|
+
* const q = new Queue<number>();
|
|
1477
|
+
* console.log(q.length); // 0;
|
|
1478
|
+
* q.push(1);
|
|
1479
|
+
* q.push(2);
|
|
1480
|
+
* console.log(q.length); // 2;
|
|
1481
|
+
*/
|
|
1136
1482
|
get length() {
|
|
1137
1483
|
return this.elements.length - this._offset;
|
|
1138
1484
|
}
|
|
1139
1485
|
/**
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1486
|
+
* Get the first element (front) without removing it.
|
|
1487
|
+
* @remarks Time O(1), Space O(1)
|
|
1488
|
+
* @returns Front element or undefined.
|
|
1489
|
+
|
|
1490
|
+
|
|
1491
|
+
|
|
1492
|
+
|
|
1493
|
+
|
|
1494
|
+
|
|
1495
|
+
|
|
1496
|
+
|
|
1497
|
+
|
|
1498
|
+
|
|
1499
|
+
|
|
1500
|
+
* @example
|
|
1501
|
+
* // View the front element
|
|
1502
|
+
* const q = new Queue<string>(['first', 'second', 'third']);
|
|
1503
|
+
* console.log(q.first); // 'first';
|
|
1504
|
+
* console.log(q.length); // 3;
|
|
1505
|
+
*/
|
|
1144
1506
|
get first() {
|
|
1145
1507
|
return this.length > 0 ? this.elements[this._offset] : void 0;
|
|
1146
1508
|
}
|
|
@@ -1163,19 +1525,69 @@ var graphTyped = (() => {
|
|
|
1163
1525
|
return new _Queue(elements);
|
|
1164
1526
|
}
|
|
1165
1527
|
/**
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1528
|
+
* Check whether the queue is empty.
|
|
1529
|
+
* @remarks Time O(1), Space O(1)
|
|
1530
|
+
* @returns True if length is 0.
|
|
1531
|
+
|
|
1532
|
+
|
|
1533
|
+
|
|
1534
|
+
|
|
1535
|
+
|
|
1536
|
+
|
|
1537
|
+
|
|
1538
|
+
|
|
1539
|
+
|
|
1540
|
+
|
|
1541
|
+
|
|
1542
|
+
* @example
|
|
1543
|
+
* // Queue for...of iteration and isEmpty check
|
|
1544
|
+
* const queue = new Queue<string>(['A', 'B', 'C', 'D']);
|
|
1545
|
+
*
|
|
1546
|
+
* const elements: string[] = [];
|
|
1547
|
+
* for (const item of queue) {
|
|
1548
|
+
* elements.push(item);
|
|
1549
|
+
* }
|
|
1550
|
+
*
|
|
1551
|
+
* // Verify all elements are iterated in order
|
|
1552
|
+
* console.log(elements); // ['A', 'B', 'C', 'D'];
|
|
1553
|
+
*
|
|
1554
|
+
* // Process all elements
|
|
1555
|
+
* while (queue.length > 0) {
|
|
1556
|
+
* queue.shift();
|
|
1557
|
+
* }
|
|
1558
|
+
*
|
|
1559
|
+
* console.log(queue.length); // 0;
|
|
1560
|
+
*/
|
|
1170
1561
|
isEmpty() {
|
|
1171
1562
|
return this.length === 0;
|
|
1172
1563
|
}
|
|
1173
1564
|
/**
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
1565
|
+
* Enqueue one element at the back.
|
|
1566
|
+
* @remarks Time O(1), Space O(1)
|
|
1567
|
+
* @param element - Element to enqueue.
|
|
1568
|
+
* @returns True on success.
|
|
1569
|
+
|
|
1570
|
+
|
|
1571
|
+
|
|
1572
|
+
|
|
1573
|
+
|
|
1574
|
+
|
|
1575
|
+
|
|
1576
|
+
|
|
1577
|
+
|
|
1578
|
+
|
|
1579
|
+
|
|
1580
|
+
* @example
|
|
1581
|
+
* // basic Queue creation and push operation
|
|
1582
|
+
* // Create a simple Queue with initial values
|
|
1583
|
+
* const queue = new Queue([1, 2, 3, 4, 5]);
|
|
1584
|
+
*
|
|
1585
|
+
* // Verify the queue maintains insertion order
|
|
1586
|
+
* console.log([...queue]); // [1, 2, 3, 4, 5];
|
|
1587
|
+
*
|
|
1588
|
+
* // Check length
|
|
1589
|
+
* console.log(queue.length); // 5;
|
|
1590
|
+
*/
|
|
1179
1591
|
push(element) {
|
|
1180
1592
|
this.elements.push(element);
|
|
1181
1593
|
if (this._maxLen > 0 && this.length > this._maxLen) this.shift();
|
|
@@ -1196,10 +1608,35 @@ var graphTyped = (() => {
|
|
|
1196
1608
|
return ans;
|
|
1197
1609
|
}
|
|
1198
1610
|
/**
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1611
|
+
* Dequeue one element from the front (amortized via offset).
|
|
1612
|
+
* @remarks Time O(1) amortized, Space O(1)
|
|
1613
|
+
* @returns Removed element or undefined.
|
|
1614
|
+
|
|
1615
|
+
|
|
1616
|
+
|
|
1617
|
+
|
|
1618
|
+
|
|
1619
|
+
|
|
1620
|
+
|
|
1621
|
+
|
|
1622
|
+
|
|
1623
|
+
|
|
1624
|
+
|
|
1625
|
+
* @example
|
|
1626
|
+
* // Queue shift and peek operations
|
|
1627
|
+
* const queue = new Queue<number>([10, 20, 30, 40]);
|
|
1628
|
+
*
|
|
1629
|
+
* // Peek at the front element without removing it
|
|
1630
|
+
* console.log(queue.first); // 10;
|
|
1631
|
+
*
|
|
1632
|
+
* // Remove and get the first element (FIFO)
|
|
1633
|
+
* const first = queue.shift();
|
|
1634
|
+
* console.log(first); // 10;
|
|
1635
|
+
*
|
|
1636
|
+
* // Verify remaining elements and length decreased
|
|
1637
|
+
* console.log([...queue]); // [20, 30, 40];
|
|
1638
|
+
* console.log(queue.length); // 3;
|
|
1639
|
+
*/
|
|
1203
1640
|
shift() {
|
|
1204
1641
|
if (this.length === 0) return void 0;
|
|
1205
1642
|
const first = this.first;
|
|
@@ -1208,11 +1645,24 @@ var graphTyped = (() => {
|
|
|
1208
1645
|
return first;
|
|
1209
1646
|
}
|
|
1210
1647
|
/**
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1648
|
+
* Delete the first occurrence of a specific element.
|
|
1649
|
+
* @remarks Time O(N), Space O(1)
|
|
1650
|
+
* @param element - Element to remove (strict equality via Object.is).
|
|
1651
|
+
* @returns True if an element was removed.
|
|
1652
|
+
|
|
1653
|
+
|
|
1654
|
+
|
|
1655
|
+
|
|
1656
|
+
|
|
1657
|
+
|
|
1658
|
+
|
|
1659
|
+
|
|
1660
|
+
* @example
|
|
1661
|
+
* // Remove specific element
|
|
1662
|
+
* const q = new Queue<number>([1, 2, 3, 2]);
|
|
1663
|
+
* q.delete(2);
|
|
1664
|
+
* console.log(q.length); // 3;
|
|
1665
|
+
*/
|
|
1216
1666
|
delete(element) {
|
|
1217
1667
|
for (let i = this._offset; i < this.elements.length; i++) {
|
|
1218
1668
|
if (Object.is(this.elements[i], element)) {
|
|
@@ -1223,11 +1673,24 @@ var graphTyped = (() => {
|
|
|
1223
1673
|
return false;
|
|
1224
1674
|
}
|
|
1225
1675
|
/**
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1676
|
+
* Get the element at a given logical index.
|
|
1677
|
+
* @remarks Time O(1), Space O(1)
|
|
1678
|
+
* @param index - Zero-based index from the front.
|
|
1679
|
+
* @returns Element or undefined.
|
|
1680
|
+
|
|
1681
|
+
|
|
1682
|
+
|
|
1683
|
+
|
|
1684
|
+
|
|
1685
|
+
|
|
1686
|
+
|
|
1687
|
+
|
|
1688
|
+
* @example
|
|
1689
|
+
* // Access element by index
|
|
1690
|
+
* const q = new Queue<string>(['a', 'b', 'c']);
|
|
1691
|
+
* console.log(q.at(0)); // 'a';
|
|
1692
|
+
* console.log(q.at(2)); // 'c';
|
|
1693
|
+
*/
|
|
1231
1694
|
at(index) {
|
|
1232
1695
|
if (index < 0 || index >= this.length) return void 0;
|
|
1233
1696
|
return this._elements[this._offset + index];
|
|
@@ -1279,19 +1742,48 @@ var graphTyped = (() => {
|
|
|
1279
1742
|
return this;
|
|
1280
1743
|
}
|
|
1281
1744
|
/**
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1745
|
+
* Remove all elements and reset offset.
|
|
1746
|
+
* @remarks Time O(1), Space O(1)
|
|
1747
|
+
* @returns void
|
|
1748
|
+
|
|
1749
|
+
|
|
1750
|
+
|
|
1751
|
+
|
|
1752
|
+
|
|
1753
|
+
|
|
1754
|
+
|
|
1755
|
+
|
|
1756
|
+
|
|
1757
|
+
* @example
|
|
1758
|
+
* // Remove all elements
|
|
1759
|
+
* const q = new Queue<number>([1, 2, 3]);
|
|
1760
|
+
* q.clear();
|
|
1761
|
+
* console.log(q.length); // 0;
|
|
1762
|
+
*/
|
|
1286
1763
|
clear() {
|
|
1287
1764
|
this._elements = [];
|
|
1288
1765
|
this._offset = 0;
|
|
1289
1766
|
}
|
|
1290
1767
|
/**
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1768
|
+
* Compact storage by discarding consumed head elements.
|
|
1769
|
+
* @remarks Time O(N), Space O(N)
|
|
1770
|
+
* @returns True when compaction performed.
|
|
1771
|
+
|
|
1772
|
+
|
|
1773
|
+
|
|
1774
|
+
|
|
1775
|
+
|
|
1776
|
+
|
|
1777
|
+
|
|
1778
|
+
|
|
1779
|
+
* @example
|
|
1780
|
+
* // Reclaim unused memory
|
|
1781
|
+
* const q = new Queue<number>([1, 2, 3, 4, 5]);
|
|
1782
|
+
* q.shift();
|
|
1783
|
+
* q.shift();
|
|
1784
|
+
* q.compact();
|
|
1785
|
+
* console.log(q.length); // 3;
|
|
1786
|
+
*/
|
|
1295
1787
|
compact() {
|
|
1296
1788
|
this._elements = this.elements.slice(this._offset);
|
|
1297
1789
|
this._offset = 0;
|
|
@@ -1317,10 +1809,26 @@ var graphTyped = (() => {
|
|
|
1317
1809
|
return removed;
|
|
1318
1810
|
}
|
|
1319
1811
|
/**
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
1812
|
+
* Deep clone this queue and its parameters.
|
|
1813
|
+
* @remarks Time O(N), Space O(N)
|
|
1814
|
+
* @returns A new queue with the same content and options.
|
|
1815
|
+
|
|
1816
|
+
|
|
1817
|
+
|
|
1818
|
+
|
|
1819
|
+
|
|
1820
|
+
|
|
1821
|
+
|
|
1822
|
+
|
|
1823
|
+
|
|
1824
|
+
* @example
|
|
1825
|
+
* // Create independent copy
|
|
1826
|
+
* const q = new Queue<number>([1, 2, 3]);
|
|
1827
|
+
* const copy = q.clone();
|
|
1828
|
+
* copy.shift();
|
|
1829
|
+
* console.log(q.length); // 3;
|
|
1830
|
+
* console.log(copy.length); // 2;
|
|
1831
|
+
*/
|
|
1324
1832
|
clone() {
|
|
1325
1833
|
const out = this._createInstance({ toElementFn: this.toElementFn, maxLen: this._maxLen });
|
|
1326
1834
|
out._setAutoCompactRatio(this._autoCompactRatio);
|
|
@@ -1328,12 +1836,26 @@ var graphTyped = (() => {
|
|
|
1328
1836
|
return out;
|
|
1329
1837
|
}
|
|
1330
1838
|
/**
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
-
|
|
1839
|
+
* Filter elements into a new queue of the same class.
|
|
1840
|
+
* @remarks Time O(N), Space O(N)
|
|
1841
|
+
* @param predicate - Predicate (element, index, queue) → boolean to keep element.
|
|
1842
|
+
* @param [thisArg] - Value for `this` inside the predicate.
|
|
1843
|
+
* @returns A new queue with kept elements.
|
|
1844
|
+
|
|
1845
|
+
|
|
1846
|
+
|
|
1847
|
+
|
|
1848
|
+
|
|
1849
|
+
|
|
1850
|
+
|
|
1851
|
+
|
|
1852
|
+
|
|
1853
|
+
* @example
|
|
1854
|
+
* // Filter elements
|
|
1855
|
+
* const q = new Queue<number>([1, 2, 3, 4, 5]);
|
|
1856
|
+
* const evens = q.filter(x => x % 2 === 0);
|
|
1857
|
+
* console.log(evens.length); // 2;
|
|
1858
|
+
*/
|
|
1337
1859
|
filter(predicate, thisArg) {
|
|
1338
1860
|
const out = this._createInstance({ toElementFn: this.toElementFn, maxLen: this._maxLen });
|
|
1339
1861
|
out._setAutoCompactRatio(this._autoCompactRatio);
|
|
@@ -1345,15 +1867,28 @@ var graphTyped = (() => {
|
|
|
1345
1867
|
return out;
|
|
1346
1868
|
}
|
|
1347
1869
|
/**
|
|
1348
|
-
|
|
1349
|
-
|
|
1350
|
-
|
|
1351
|
-
|
|
1352
|
-
|
|
1353
|
-
|
|
1354
|
-
|
|
1355
|
-
|
|
1356
|
-
|
|
1870
|
+
* Map each element to a new element in a possibly different-typed queue.
|
|
1871
|
+
* @remarks Time O(N), Space O(N)
|
|
1872
|
+
* @template EM
|
|
1873
|
+
* @template RM
|
|
1874
|
+
* @param callback - Mapping function (element, index, queue) → newElement.
|
|
1875
|
+
* @param [options] - Options for the output queue (e.g., toElementFn, maxLen, autoCompactRatio).
|
|
1876
|
+
* @param [thisArg] - Value for `this` inside the callback.
|
|
1877
|
+
* @returns A new Queue with mapped elements.
|
|
1878
|
+
|
|
1879
|
+
|
|
1880
|
+
|
|
1881
|
+
|
|
1882
|
+
|
|
1883
|
+
|
|
1884
|
+
|
|
1885
|
+
|
|
1886
|
+
* @example
|
|
1887
|
+
* // Transform elements
|
|
1888
|
+
* const q = new Queue<number>([1, 2, 3]);
|
|
1889
|
+
* const doubled = q.map(x => x * 2);
|
|
1890
|
+
* console.log(doubled.toArray()); // [2, 4, 6];
|
|
1891
|
+
*/
|
|
1357
1892
|
map(callback, options, thisArg) {
|
|
1358
1893
|
var _a, _b;
|
|
1359
1894
|
const out = new this.constructor([], {
|
|
@@ -1576,7 +2111,7 @@ var graphTyped = (() => {
|
|
|
1576
2111
|
const newEdge = this.createEdge(srcOrEdge, dest, weight, value);
|
|
1577
2112
|
return this._addEdge(newEdge);
|
|
1578
2113
|
} else {
|
|
1579
|
-
throw new
|
|
2114
|
+
throw new TypeError(ERR.invalidArgument("dest must be a Vertex or vertex key when srcOrEdge is an Edge.", "Graph"));
|
|
1580
2115
|
}
|
|
1581
2116
|
}
|
|
1582
2117
|
}
|
|
@@ -2260,6 +2795,94 @@ var graphTyped = (() => {
|
|
|
2260
2795
|
_getVertexKey(vertexOrKey) {
|
|
2261
2796
|
return vertexOrKey instanceof AbstractVertex ? vertexOrKey.key : vertexOrKey;
|
|
2262
2797
|
}
|
|
2798
|
+
/**
|
|
2799
|
+
* The edge connector string used in visual output.
|
|
2800
|
+
* Override in subclasses (e.g., '--' for undirected, '->' for directed).
|
|
2801
|
+
*/
|
|
2802
|
+
get _edgeConnector() {
|
|
2803
|
+
return "--";
|
|
2804
|
+
}
|
|
2805
|
+
/**
|
|
2806
|
+
* Generate a text-based visual representation of the graph.
|
|
2807
|
+
*
|
|
2808
|
+
* **Adjacency list format:**
|
|
2809
|
+
* ```
|
|
2810
|
+
* Graph (5 vertices, 6 edges):
|
|
2811
|
+
* A -> B (1), C (2)
|
|
2812
|
+
* B -> D (3)
|
|
2813
|
+
* C -> (no outgoing edges)
|
|
2814
|
+
* D -> A (1)
|
|
2815
|
+
* E (isolated)
|
|
2816
|
+
* ```
|
|
2817
|
+
*
|
|
2818
|
+
* @param options - Optional display settings.
|
|
2819
|
+
* @param options.showWeight - Whether to show edge weights (default: true).
|
|
2820
|
+
* @returns The visual string.
|
|
2821
|
+
*/
|
|
2822
|
+
toVisual(options) {
|
|
2823
|
+
var _a;
|
|
2824
|
+
const showWeight = (_a = options == null ? void 0 : options.showWeight) != null ? _a : true;
|
|
2825
|
+
const vertices = [...this._vertexMap.values()];
|
|
2826
|
+
const vertexCount = vertices.length;
|
|
2827
|
+
const edgeCount = this.edgeSet().length;
|
|
2828
|
+
const lines = [`Graph (${vertexCount} vertices, ${edgeCount} edges):`];
|
|
2829
|
+
for (const vertex of vertices) {
|
|
2830
|
+
const neighbors = this.getNeighbors(vertex);
|
|
2831
|
+
if (neighbors.length === 0) {
|
|
2832
|
+
lines.push(` ${vertex.key} (isolated)`);
|
|
2833
|
+
} else {
|
|
2834
|
+
const edgeStrs = neighbors.map((neighbor) => {
|
|
2835
|
+
const edge = this.getEdge(vertex, neighbor);
|
|
2836
|
+
if (edge && showWeight && edge.weight !== void 0 && edge.weight !== 1) {
|
|
2837
|
+
return `${neighbor.key} (${edge.weight})`;
|
|
2838
|
+
}
|
|
2839
|
+
return `${neighbor.key}`;
|
|
2840
|
+
});
|
|
2841
|
+
lines.push(` ${vertex.key} ${this._edgeConnector} ${edgeStrs.join(", ")}`);
|
|
2842
|
+
}
|
|
2843
|
+
}
|
|
2844
|
+
return lines.join("\n");
|
|
2845
|
+
}
|
|
2846
|
+
/**
|
|
2847
|
+
* Generate DOT language representation for Graphviz.
|
|
2848
|
+
*
|
|
2849
|
+
* @param options - Optional display settings.
|
|
2850
|
+
* @param options.name - Graph name (default: 'G').
|
|
2851
|
+
* @param options.showWeight - Whether to label edges with weight (default: true).
|
|
2852
|
+
* @returns DOT format string.
|
|
2853
|
+
*/
|
|
2854
|
+
toDot(options) {
|
|
2855
|
+
var _a, _b;
|
|
2856
|
+
const name = (_a = options == null ? void 0 : options.name) != null ? _a : "G";
|
|
2857
|
+
const showWeight = (_b = options == null ? void 0 : options.showWeight) != null ? _b : true;
|
|
2858
|
+
const isDirected = this._edgeConnector === "->";
|
|
2859
|
+
const graphType = isDirected ? "digraph" : "graph";
|
|
2860
|
+
const edgeOp = isDirected ? "->" : "--";
|
|
2861
|
+
const lines = [`${graphType} ${name} {`];
|
|
2862
|
+
for (const vertex of this._vertexMap.values()) {
|
|
2863
|
+
lines.push(` "${vertex.key}";`);
|
|
2864
|
+
}
|
|
2865
|
+
const visited = /* @__PURE__ */ new Set();
|
|
2866
|
+
for (const vertex of this._vertexMap.values()) {
|
|
2867
|
+
for (const neighbor of this.getNeighbors(vertex)) {
|
|
2868
|
+
const edgeId = isDirected ? `${vertex.key}->${neighbor.key}` : [vertex.key, neighbor.key].sort().join("--");
|
|
2869
|
+
if (visited.has(edgeId)) continue;
|
|
2870
|
+
visited.add(edgeId);
|
|
2871
|
+
const edge = this.getEdge(vertex, neighbor);
|
|
2872
|
+
const label = edge && showWeight && edge.weight !== void 0 && edge.weight !== 1 ? ` [label="${edge.weight}"]` : "";
|
|
2873
|
+
lines.push(` "${vertex.key}" ${edgeOp} "${neighbor.key}"${label};`);
|
|
2874
|
+
}
|
|
2875
|
+
}
|
|
2876
|
+
lines.push("}");
|
|
2877
|
+
return lines.join("\n");
|
|
2878
|
+
}
|
|
2879
|
+
/**
|
|
2880
|
+
* Print the graph to console.
|
|
2881
|
+
* @param options - Display settings passed to `toVisual`.
|
|
2882
|
+
*/
|
|
2883
|
+
print(options) {
|
|
2884
|
+
console.log(this.toVisual(options));
|
|
2885
|
+
}
|
|
2263
2886
|
};
|
|
2264
2887
|
|
|
2265
2888
|
// src/data-structures/graph/directed-graph.ts
|
|
@@ -2288,6 +2911,9 @@ var graphTyped = (() => {
|
|
|
2288
2911
|
__publicField(this, "_outEdgeMap", /* @__PURE__ */ new Map());
|
|
2289
2912
|
__publicField(this, "_inEdgeMap", /* @__PURE__ */ new Map());
|
|
2290
2913
|
}
|
|
2914
|
+
get _edgeConnector() {
|
|
2915
|
+
return "->";
|
|
2916
|
+
}
|
|
2291
2917
|
get outEdgeMap() {
|
|
2292
2918
|
return this._outEdgeMap;
|
|
2293
2919
|
}
|
|
@@ -2350,12 +2976,28 @@ var graphTyped = (() => {
|
|
|
2350
2976
|
return new DirectedEdge(src, dest, (_a = weight != null ? weight : this.options.defaultEdgeWeight) != null ? _a : 1, value);
|
|
2351
2977
|
}
|
|
2352
2978
|
/**
|
|
2353
|
-
|
|
2354
|
-
|
|
2355
|
-
|
|
2356
|
-
|
|
2357
|
-
|
|
2358
|
-
|
|
2979
|
+
* Get the unique edge from `src` to `dest`, if present.
|
|
2980
|
+
* @param srcOrKey - Source vertex or key.
|
|
2981
|
+
* @param destOrKey - Destination vertex or key.
|
|
2982
|
+
* @returns Edge instance or `undefined`.
|
|
2983
|
+
* @remarks Time O(1) avg, Space O(1)
|
|
2984
|
+
|
|
2985
|
+
|
|
2986
|
+
|
|
2987
|
+
|
|
2988
|
+
|
|
2989
|
+
|
|
2990
|
+
|
|
2991
|
+
|
|
2992
|
+
* @example
|
|
2993
|
+
* // Get edge between vertices
|
|
2994
|
+
* const g = new DirectedGraph();
|
|
2995
|
+
* g.addVertex('A');
|
|
2996
|
+
* g.addVertex('B');
|
|
2997
|
+
* g.addEdge('A', 'B', 5);
|
|
2998
|
+
* const edge = g.getEdge('A', 'B');
|
|
2999
|
+
* console.log(edge?.weight); // 5;
|
|
3000
|
+
*/
|
|
2359
3001
|
getEdge(srcOrKey, destOrKey) {
|
|
2360
3002
|
let edgeMap = [];
|
|
2361
3003
|
if (srcOrKey !== void 0 && destOrKey !== void 0) {
|
|
@@ -2395,12 +3037,48 @@ var graphTyped = (() => {
|
|
|
2395
3037
|
return removed;
|
|
2396
3038
|
}
|
|
2397
3039
|
/**
|
|
2398
|
-
|
|
2399
|
-
|
|
2400
|
-
|
|
2401
|
-
|
|
2402
|
-
|
|
2403
|
-
|
|
3040
|
+
* Delete an edge by instance or by `(srcKey, destKey)`.
|
|
3041
|
+
* @param edgeOrSrcVertexKey - Edge instance or source vertex/key.
|
|
3042
|
+
* @param destVertexKey - Optional destination vertex/key when deleting by pair.
|
|
3043
|
+
* @returns Removed edge or `undefined`.
|
|
3044
|
+
* @remarks Time O(1) avg, Space O(1)
|
|
3045
|
+
|
|
3046
|
+
|
|
3047
|
+
|
|
3048
|
+
|
|
3049
|
+
|
|
3050
|
+
|
|
3051
|
+
|
|
3052
|
+
|
|
3053
|
+
|
|
3054
|
+
|
|
3055
|
+
|
|
3056
|
+
* @example
|
|
3057
|
+
* // DirectedGraph deleteEdge and vertex operations
|
|
3058
|
+
* const graph = new DirectedGraph<string>();
|
|
3059
|
+
*
|
|
3060
|
+
* // Build a small graph
|
|
3061
|
+
* graph.addVertex('X');
|
|
3062
|
+
* graph.addVertex('Y');
|
|
3063
|
+
* graph.addVertex('Z');
|
|
3064
|
+
* graph.addEdge('X', 'Y', 1);
|
|
3065
|
+
* graph.addEdge('Y', 'Z', 2);
|
|
3066
|
+
*
|
|
3067
|
+
* // Delete an edge
|
|
3068
|
+
* graph.deleteEdgeSrcToDest('X', 'Y');
|
|
3069
|
+
* console.log(graph.hasEdge('X', 'Y')); // false;
|
|
3070
|
+
*
|
|
3071
|
+
* // Edge in other direction should not exist
|
|
3072
|
+
* console.log(graph.hasEdge('Y', 'X')); // false;
|
|
3073
|
+
*
|
|
3074
|
+
* // Other edges should remain
|
|
3075
|
+
* console.log(graph.hasEdge('Y', 'Z')); // true;
|
|
3076
|
+
*
|
|
3077
|
+
* // Delete a vertex
|
|
3078
|
+
* graph.deleteVertex('Y');
|
|
3079
|
+
* console.log(graph.hasVertex('Y')); // false;
|
|
3080
|
+
* console.log(graph.size); // 2;
|
|
3081
|
+
*/
|
|
2404
3082
|
deleteEdge(edgeOrSrcVertexKey, destVertexKey) {
|
|
2405
3083
|
let removed = void 0;
|
|
2406
3084
|
let src, dest;
|
|
@@ -2427,6 +3105,26 @@ var graphTyped = (() => {
|
|
|
2427
3105
|
}
|
|
2428
3106
|
return removed;
|
|
2429
3107
|
}
|
|
3108
|
+
/**
|
|
3109
|
+
* Remove a vertex
|
|
3110
|
+
|
|
3111
|
+
|
|
3112
|
+
|
|
3113
|
+
|
|
3114
|
+
|
|
3115
|
+
|
|
3116
|
+
|
|
3117
|
+
|
|
3118
|
+
* @example
|
|
3119
|
+
* // Remove a vertex
|
|
3120
|
+
* const g = new DirectedGraph();
|
|
3121
|
+
* g.addVertex('A');
|
|
3122
|
+
* g.addVertex('B');
|
|
3123
|
+
* g.addEdge('A', 'B');
|
|
3124
|
+
* g.deleteVertex('A');
|
|
3125
|
+
* console.log(g.hasVertex('A')); // false;
|
|
3126
|
+
* console.log(g.hasEdge('A', 'B')); // false;
|
|
3127
|
+
*/
|
|
2430
3128
|
deleteVertex(vertexOrKey) {
|
|
2431
3129
|
let vertexKey;
|
|
2432
3130
|
let vertex;
|
|
@@ -2458,11 +3156,28 @@ var graphTyped = (() => {
|
|
|
2458
3156
|
return removed;
|
|
2459
3157
|
}
|
|
2460
3158
|
/**
|
|
2461
|
-
|
|
2462
|
-
|
|
2463
|
-
|
|
2464
|
-
|
|
2465
|
-
|
|
3159
|
+
* Incoming edges of a vertex.
|
|
3160
|
+
* @param vertexOrKey - Vertex or key.
|
|
3161
|
+
* @returns Array of incoming edges.
|
|
3162
|
+
* @remarks Time O(deg_in), Space O(deg_in)
|
|
3163
|
+
|
|
3164
|
+
|
|
3165
|
+
|
|
3166
|
+
|
|
3167
|
+
|
|
3168
|
+
|
|
3169
|
+
|
|
3170
|
+
|
|
3171
|
+
* @example
|
|
3172
|
+
* // Get incoming edges
|
|
3173
|
+
* const g = new DirectedGraph();
|
|
3174
|
+
* g.addVertex('A');
|
|
3175
|
+
* g.addVertex('B');
|
|
3176
|
+
* g.addVertex('C');
|
|
3177
|
+
* g.addEdge('A', 'C');
|
|
3178
|
+
* g.addEdge('B', 'C');
|
|
3179
|
+
* console.log(g.incomingEdgesOf('C').length); // 2;
|
|
3180
|
+
*/
|
|
2466
3181
|
incomingEdgesOf(vertexOrKey) {
|
|
2467
3182
|
const target = this._getVertex(vertexOrKey);
|
|
2468
3183
|
if (target) {
|
|
@@ -2471,11 +3186,28 @@ var graphTyped = (() => {
|
|
|
2471
3186
|
return [];
|
|
2472
3187
|
}
|
|
2473
3188
|
/**
|
|
2474
|
-
|
|
2475
|
-
|
|
2476
|
-
|
|
2477
|
-
|
|
2478
|
-
|
|
3189
|
+
* Outgoing edges of a vertex.
|
|
3190
|
+
* @param vertexOrKey - Vertex or key.
|
|
3191
|
+
* @returns Array of outgoing edges.
|
|
3192
|
+
* @remarks Time O(deg_out), Space O(deg_out)
|
|
3193
|
+
|
|
3194
|
+
|
|
3195
|
+
|
|
3196
|
+
|
|
3197
|
+
|
|
3198
|
+
|
|
3199
|
+
|
|
3200
|
+
|
|
3201
|
+
* @example
|
|
3202
|
+
* // Get outgoing edges
|
|
3203
|
+
* const g = new DirectedGraph();
|
|
3204
|
+
* g.addVertex('A');
|
|
3205
|
+
* g.addVertex('B');
|
|
3206
|
+
* g.addVertex('C');
|
|
3207
|
+
* g.addEdge('A', 'B');
|
|
3208
|
+
* g.addEdge('A', 'C');
|
|
3209
|
+
* console.log(g.outgoingEdgesOf('A').length); // 2;
|
|
3210
|
+
*/
|
|
2479
3211
|
outgoingEdgesOf(vertexOrKey) {
|
|
2480
3212
|
const target = this._getVertex(vertexOrKey);
|
|
2481
3213
|
if (target) {
|
|
@@ -2534,11 +3266,44 @@ var graphTyped = (() => {
|
|
|
2534
3266
|
return destinations;
|
|
2535
3267
|
}
|
|
2536
3268
|
/**
|
|
2537
|
-
|
|
2538
|
-
|
|
2539
|
-
|
|
2540
|
-
|
|
2541
|
-
|
|
3269
|
+
* Topological sort if DAG; returns `undefined` if a cycle exists.
|
|
3270
|
+
* @param propertyName - `'key'` to map to keys; `'vertex'` to keep instances.
|
|
3271
|
+
* @returns Array of keys/vertices, or `undefined` when cycle is found.
|
|
3272
|
+
* @remarks Time O(V + E), Space O(V)
|
|
3273
|
+
|
|
3274
|
+
|
|
3275
|
+
|
|
3276
|
+
|
|
3277
|
+
|
|
3278
|
+
|
|
3279
|
+
|
|
3280
|
+
|
|
3281
|
+
|
|
3282
|
+
|
|
3283
|
+
|
|
3284
|
+
* @example
|
|
3285
|
+
* // DirectedGraph topologicalSort for task scheduling
|
|
3286
|
+
* const graph = new DirectedGraph<string>();
|
|
3287
|
+
*
|
|
3288
|
+
* // Build a DAG (Directed Acyclic Graph) for task dependencies
|
|
3289
|
+
* graph.addVertex('Design');
|
|
3290
|
+
* graph.addVertex('Implement');
|
|
3291
|
+
* graph.addVertex('Test');
|
|
3292
|
+
* graph.addVertex('Deploy');
|
|
3293
|
+
*
|
|
3294
|
+
* // Add dependency edges
|
|
3295
|
+
* graph.addEdge('Design', 'Implement', 1); // Design must come before Implement
|
|
3296
|
+
* graph.addEdge('Implement', 'Test', 1); // Implement must come before Test
|
|
3297
|
+
* graph.addEdge('Test', 'Deploy', 1); // Test must come before Deploy
|
|
3298
|
+
*
|
|
3299
|
+
* // Topological sort gives valid execution order
|
|
3300
|
+
* const executionOrder = graph.topologicalSort();
|
|
3301
|
+
* console.log(executionOrder); // defined;
|
|
3302
|
+
* console.log(executionOrder); // ['Design', 'Implement', 'Test', 'Deploy'];
|
|
3303
|
+
*
|
|
3304
|
+
* // All vertices should be included
|
|
3305
|
+
* console.log(executionOrder?.length); // 4;
|
|
3306
|
+
*/
|
|
2542
3307
|
topologicalSort(propertyName) {
|
|
2543
3308
|
propertyName = propertyName != null ? propertyName : "key";
|
|
2544
3309
|
const statusMap = /* @__PURE__ */ new Map();
|
|
@@ -2570,6 +3335,24 @@ var graphTyped = (() => {
|
|
|
2570
3335
|
if (propertyName === "key") sorted = sorted.map((vertex) => vertex instanceof DirectedVertex ? vertex.key : vertex);
|
|
2571
3336
|
return sorted.reverse();
|
|
2572
3337
|
}
|
|
3338
|
+
/**
|
|
3339
|
+
* Get all edges
|
|
3340
|
+
|
|
3341
|
+
|
|
3342
|
+
|
|
3343
|
+
|
|
3344
|
+
|
|
3345
|
+
|
|
3346
|
+
|
|
3347
|
+
|
|
3348
|
+
* @example
|
|
3349
|
+
* // Get all edges
|
|
3350
|
+
* const g = new DirectedGraph();
|
|
3351
|
+
* g.addVertex('A');
|
|
3352
|
+
* g.addVertex('B');
|
|
3353
|
+
* g.addEdge('A', 'B', 3);
|
|
3354
|
+
* console.log(g.edgeSet().length); // 1;
|
|
3355
|
+
*/
|
|
2573
3356
|
edgeSet() {
|
|
2574
3357
|
let edgeMap = [];
|
|
2575
3358
|
this._outEdgeMap.forEach((outEdges) => {
|
|
@@ -2577,6 +3360,28 @@ var graphTyped = (() => {
|
|
|
2577
3360
|
});
|
|
2578
3361
|
return edgeMap;
|
|
2579
3362
|
}
|
|
3363
|
+
/**
|
|
3364
|
+
* Get outgoing neighbors
|
|
3365
|
+
|
|
3366
|
+
|
|
3367
|
+
|
|
3368
|
+
|
|
3369
|
+
|
|
3370
|
+
|
|
3371
|
+
|
|
3372
|
+
|
|
3373
|
+
|
|
3374
|
+
* @example
|
|
3375
|
+
* // Get outgoing neighbors
|
|
3376
|
+
* const g = new DirectedGraph();
|
|
3377
|
+
* g.addVertex('A');
|
|
3378
|
+
* g.addVertex('B');
|
|
3379
|
+
* g.addVertex('C');
|
|
3380
|
+
* g.addEdge('A', 'B');
|
|
3381
|
+
* g.addEdge('A', 'C');
|
|
3382
|
+
* const neighbors = g.getNeighbors('A');
|
|
3383
|
+
* console.log(neighbors.map(v => v.key).sort()); // ['B', 'C'];
|
|
3384
|
+
*/
|
|
2580
3385
|
getNeighbors(vertexOrKey) {
|
|
2581
3386
|
const neighbors = [];
|
|
2582
3387
|
const vertex = this._getVertex(vertexOrKey);
|
|
@@ -2634,10 +3439,31 @@ var graphTyped = (() => {
|
|
|
2634
3439
|
return super.clone();
|
|
2635
3440
|
}
|
|
2636
3441
|
/**
|
|
2637
|
-
|
|
2638
|
-
|
|
2639
|
-
|
|
2640
|
-
|
|
3442
|
+
* Tarjan's algorithm for strongly connected components.
|
|
3443
|
+
* @returns `{ dfnMap, lowMap, SCCs }`.
|
|
3444
|
+
* @remarks Time O(V + E), Space O(V + E)
|
|
3445
|
+
|
|
3446
|
+
|
|
3447
|
+
|
|
3448
|
+
|
|
3449
|
+
|
|
3450
|
+
|
|
3451
|
+
|
|
3452
|
+
|
|
3453
|
+
* @example
|
|
3454
|
+
* // Find strongly connected components
|
|
3455
|
+
* const g = new DirectedGraph();
|
|
3456
|
+
* g.addVertex('A');
|
|
3457
|
+
* g.addVertex('B');
|
|
3458
|
+
* g.addVertex('C');
|
|
3459
|
+
* g.addEdge('A', 'B');
|
|
3460
|
+
* g.addEdge('B', 'C');
|
|
3461
|
+
* g.addEdge('C', 'A');
|
|
3462
|
+
* const { SCCs } = g.tarjan();
|
|
3463
|
+
* // A→B→C→A forms one SCC with 3 members
|
|
3464
|
+
* const sccArrays = [...SCCs.values()];
|
|
3465
|
+
* console.log(sccArrays.some(scc => scc.length === 3)); // true;
|
|
3466
|
+
*/
|
|
2641
3467
|
tarjan() {
|
|
2642
3468
|
const dfnMap = /* @__PURE__ */ new Map();
|
|
2643
3469
|
const lowMap = /* @__PURE__ */ new Map();
|
|
@@ -2695,10 +3521,29 @@ var graphTyped = (() => {
|
|
|
2695
3521
|
return this.tarjan().lowMap;
|
|
2696
3522
|
}
|
|
2697
3523
|
/**
|
|
2698
|
-
|
|
2699
|
-
|
|
2700
|
-
|
|
2701
|
-
|
|
3524
|
+
* Strongly connected components computed by `tarjan()`.
|
|
3525
|
+
* @returns Map from SCC id to vertices.
|
|
3526
|
+
* @remarks Time O(#SCC + V), Space O(V)
|
|
3527
|
+
|
|
3528
|
+
|
|
3529
|
+
|
|
3530
|
+
|
|
3531
|
+
|
|
3532
|
+
|
|
3533
|
+
|
|
3534
|
+
|
|
3535
|
+
* @example
|
|
3536
|
+
* // Get strongly connected components
|
|
3537
|
+
* const g = new DirectedGraph();
|
|
3538
|
+
* g.addVertex(1);
|
|
3539
|
+
* g.addVertex(2);
|
|
3540
|
+
* g.addVertex(3);
|
|
3541
|
+
* g.addEdge(1, 2);
|
|
3542
|
+
* g.addEdge(2, 3);
|
|
3543
|
+
* g.addEdge(3, 1);
|
|
3544
|
+
* const sccs = g.getSCCs(); // Map<number, VO[]>
|
|
3545
|
+
* console.log(sccs.size); // >= 1;
|
|
3546
|
+
*/
|
|
2702
3547
|
getSCCs() {
|
|
2703
3548
|
return this.tarjan().SCCs;
|
|
2704
3549
|
}
|
|
@@ -2814,12 +3659,27 @@ var graphTyped = (() => {
|
|
|
2814
3659
|
return new UndirectedEdge(v1, v2, (_a = weight != null ? weight : this.options.defaultEdgeWeight) != null ? _a : 1, value);
|
|
2815
3660
|
}
|
|
2816
3661
|
/**
|
|
2817
|
-
|
|
2818
|
-
|
|
2819
|
-
|
|
2820
|
-
|
|
2821
|
-
|
|
2822
|
-
|
|
3662
|
+
* Get an undirected edge between two vertices, if present.
|
|
3663
|
+
* @param v1 - One vertex or key.
|
|
3664
|
+
* @param v2 - The other vertex or key.
|
|
3665
|
+
* @returns Edge instance or `undefined`.
|
|
3666
|
+
* @remarks Time O(1) avg, Space O(1)
|
|
3667
|
+
|
|
3668
|
+
|
|
3669
|
+
|
|
3670
|
+
|
|
3671
|
+
|
|
3672
|
+
|
|
3673
|
+
|
|
3674
|
+
|
|
3675
|
+
* @example
|
|
3676
|
+
* // Get edge between vertices
|
|
3677
|
+
* const g = new UndirectedGraph();
|
|
3678
|
+
* g.addVertex('A');
|
|
3679
|
+
* g.addVertex('B');
|
|
3680
|
+
* g.addEdge('A', 'B', 7);
|
|
3681
|
+
* console.log(g.getEdge('A', 'B')?.weight); // 7;
|
|
3682
|
+
*/
|
|
2823
3683
|
getEdge(v1, v2) {
|
|
2824
3684
|
var _a;
|
|
2825
3685
|
let edgeMap = [];
|
|
@@ -2857,12 +3717,50 @@ var graphTyped = (() => {
|
|
|
2857
3717
|
return removed;
|
|
2858
3718
|
}
|
|
2859
3719
|
/**
|
|
2860
|
-
|
|
2861
|
-
|
|
2862
|
-
|
|
2863
|
-
|
|
2864
|
-
|
|
2865
|
-
|
|
3720
|
+
* Delete an edge by instance or by a pair of keys.
|
|
3721
|
+
* @param edgeOrOneSideVertexKey - Edge instance or one endpoint vertex/key.
|
|
3722
|
+
* @param otherSideVertexKey - Required second endpoint when deleting by pair.
|
|
3723
|
+
* @returns Removed edge or `undefined`.
|
|
3724
|
+
* @remarks Time O(1) avg, Space O(1)
|
|
3725
|
+
|
|
3726
|
+
|
|
3727
|
+
|
|
3728
|
+
|
|
3729
|
+
|
|
3730
|
+
|
|
3731
|
+
|
|
3732
|
+
|
|
3733
|
+
|
|
3734
|
+
|
|
3735
|
+
|
|
3736
|
+
* @example
|
|
3737
|
+
* // UndirectedGraph deleteEdge and vertex operations
|
|
3738
|
+
* const graph = new UndirectedGraph<string>();
|
|
3739
|
+
*
|
|
3740
|
+
* // Build a simple undirected graph
|
|
3741
|
+
* graph.addVertex('X');
|
|
3742
|
+
* graph.addVertex('Y');
|
|
3743
|
+
* graph.addVertex('Z');
|
|
3744
|
+
* graph.addEdge('X', 'Y', 1);
|
|
3745
|
+
* graph.addEdge('Y', 'Z', 2);
|
|
3746
|
+
* graph.addEdge('X', 'Z', 3);
|
|
3747
|
+
*
|
|
3748
|
+
* // Delete an edge
|
|
3749
|
+
* graph.deleteEdge('X', 'Y');
|
|
3750
|
+
* console.log(graph.hasEdge('X', 'Y')); // false;
|
|
3751
|
+
*
|
|
3752
|
+
* // Bidirectional deletion confirmed
|
|
3753
|
+
* console.log(graph.hasEdge('Y', 'X')); // false;
|
|
3754
|
+
*
|
|
3755
|
+
* // Other edges should remain
|
|
3756
|
+
* console.log(graph.hasEdge('Y', 'Z')); // true;
|
|
3757
|
+
* console.log(graph.hasEdge('Z', 'Y')); // true;
|
|
3758
|
+
*
|
|
3759
|
+
* // Delete a vertex
|
|
3760
|
+
* graph.deleteVertex('Y');
|
|
3761
|
+
* console.log(graph.hasVertex('Y')); // false;
|
|
3762
|
+
* console.log(graph.size); // 2;
|
|
3763
|
+
*/
|
|
2866
3764
|
deleteEdge(edgeOrOneSideVertexKey, otherSideVertexKey) {
|
|
2867
3765
|
let oneSide, otherSide;
|
|
2868
3766
|
if (this.isVertexKey(edgeOrOneSideVertexKey)) {
|
|
@@ -2883,11 +3781,27 @@ var graphTyped = (() => {
|
|
|
2883
3781
|
}
|
|
2884
3782
|
}
|
|
2885
3783
|
/**
|
|
2886
|
-
|
|
2887
|
-
|
|
2888
|
-
|
|
2889
|
-
|
|
2890
|
-
|
|
3784
|
+
* Delete a vertex and remove it from all neighbor lists.
|
|
3785
|
+
* @param vertexOrKey - Vertex or key.
|
|
3786
|
+
* @returns `true` if removed; otherwise `false`.
|
|
3787
|
+
* @remarks Time O(deg), Space O(1)
|
|
3788
|
+
|
|
3789
|
+
|
|
3790
|
+
|
|
3791
|
+
|
|
3792
|
+
|
|
3793
|
+
|
|
3794
|
+
|
|
3795
|
+
|
|
3796
|
+
* @example
|
|
3797
|
+
* // Remove vertex and edges
|
|
3798
|
+
* const g = new UndirectedGraph();
|
|
3799
|
+
* g.addVertex('A');
|
|
3800
|
+
* g.addVertex('B');
|
|
3801
|
+
* g.addEdge('A', 'B');
|
|
3802
|
+
* g.deleteVertex('A');
|
|
3803
|
+
* console.log(g.hasVertex('A')); // false;
|
|
3804
|
+
*/
|
|
2891
3805
|
deleteVertex(vertexOrKey) {
|
|
2892
3806
|
let vertexKey;
|
|
2893
3807
|
let vertex;
|
|
@@ -2943,10 +3857,25 @@ var graphTyped = (() => {
|
|
|
2943
3857
|
}
|
|
2944
3858
|
}
|
|
2945
3859
|
/**
|
|
2946
|
-
|
|
2947
|
-
|
|
2948
|
-
|
|
2949
|
-
|
|
3860
|
+
* Unique set of undirected edges across endpoints.
|
|
3861
|
+
* @returns Array of edges.
|
|
3862
|
+
* @remarks Time O(E), Space O(E)
|
|
3863
|
+
|
|
3864
|
+
|
|
3865
|
+
|
|
3866
|
+
|
|
3867
|
+
|
|
3868
|
+
|
|
3869
|
+
|
|
3870
|
+
|
|
3871
|
+
* @example
|
|
3872
|
+
* // Get all edges
|
|
3873
|
+
* const g = new UndirectedGraph();
|
|
3874
|
+
* g.addVertex('A');
|
|
3875
|
+
* g.addVertex('B');
|
|
3876
|
+
* g.addEdge('A', 'B');
|
|
3877
|
+
* console.log(g.edgeSet().length); // 1;
|
|
3878
|
+
*/
|
|
2950
3879
|
edgeSet() {
|
|
2951
3880
|
const edgeSet = /* @__PURE__ */ new Set();
|
|
2952
3881
|
this._edgeMap.forEach((edgeMap) => {
|
|
@@ -2956,6 +3885,52 @@ var graphTyped = (() => {
|
|
|
2956
3885
|
});
|
|
2957
3886
|
return [...edgeSet];
|
|
2958
3887
|
}
|
|
3888
|
+
/**
|
|
3889
|
+
* UndirectedGraph connectivity and neighbors
|
|
3890
|
+
|
|
3891
|
+
|
|
3892
|
+
|
|
3893
|
+
|
|
3894
|
+
|
|
3895
|
+
|
|
3896
|
+
|
|
3897
|
+
|
|
3898
|
+
|
|
3899
|
+
|
|
3900
|
+
|
|
3901
|
+
* @example
|
|
3902
|
+
* // UndirectedGraph connectivity and neighbors
|
|
3903
|
+
* const graph = new UndirectedGraph<string>();
|
|
3904
|
+
*
|
|
3905
|
+
* // Build a friendship network
|
|
3906
|
+
* const people = ['Alice', 'Bob', 'Charlie', 'Diana', 'Eve'];
|
|
3907
|
+
* for (const person of people) {
|
|
3908
|
+
* graph.addVertex(person);
|
|
3909
|
+
* }
|
|
3910
|
+
*
|
|
3911
|
+
* // Add friendships (undirected edges)
|
|
3912
|
+
* graph.addEdge('Alice', 'Bob', 1);
|
|
3913
|
+
* graph.addEdge('Alice', 'Charlie', 1);
|
|
3914
|
+
* graph.addEdge('Bob', 'Diana', 1);
|
|
3915
|
+
* graph.addEdge('Charlie', 'Eve', 1);
|
|
3916
|
+
* graph.addEdge('Diana', 'Eve', 1);
|
|
3917
|
+
*
|
|
3918
|
+
* // Get friends of each person
|
|
3919
|
+
* const aliceFriends = graph.getNeighbors('Alice');
|
|
3920
|
+
* console.log(aliceFriends[0].key); // 'Bob';
|
|
3921
|
+
* console.log(aliceFriends[1].key); // 'Charlie';
|
|
3922
|
+
* console.log(aliceFriends.length); // 2;
|
|
3923
|
+
*
|
|
3924
|
+
* const dianaFriends = graph.getNeighbors('Diana');
|
|
3925
|
+
* console.log(dianaFriends[0].key); // 'Bob';
|
|
3926
|
+
* console.log(dianaFriends[1].key); // 'Eve';
|
|
3927
|
+
* console.log(dianaFriends.length); // 2;
|
|
3928
|
+
*
|
|
3929
|
+
* // Verify bidirectional friendship
|
|
3930
|
+
* const bobFriends = graph.getNeighbors('Bob');
|
|
3931
|
+
* console.log(bobFriends[0].key); // 'Alice'; // Alice -> Bob -> Alice ✓
|
|
3932
|
+
* console.log(bobFriends[1].key); // 'Diana';
|
|
3933
|
+
*/
|
|
2959
3934
|
getNeighbors(vertexOrKey) {
|
|
2960
3935
|
const neighbors = [];
|
|
2961
3936
|
const vertex = this._getVertex(vertexOrKey);
|
|
@@ -3012,10 +3987,28 @@ var graphTyped = (() => {
|
|
|
3012
3987
|
return super.clone();
|
|
3013
3988
|
}
|
|
3014
3989
|
/**
|
|
3015
|
-
|
|
3016
|
-
|
|
3017
|
-
|
|
3018
|
-
|
|
3990
|
+
* Tarjan-based bridge and articulation point detection.
|
|
3991
|
+
* @returns `{ dfnMap, lowMap, bridges, cutVertices }`.
|
|
3992
|
+
* @remarks Time O(V + E), Space O(V + E)
|
|
3993
|
+
|
|
3994
|
+
|
|
3995
|
+
|
|
3996
|
+
|
|
3997
|
+
|
|
3998
|
+
|
|
3999
|
+
|
|
4000
|
+
|
|
4001
|
+
* @example
|
|
4002
|
+
* // Find articulation points and bridges
|
|
4003
|
+
* const g = new UndirectedGraph();
|
|
4004
|
+
* g.addVertex('A');
|
|
4005
|
+
* g.addVertex('B');
|
|
4006
|
+
* g.addVertex('C');
|
|
4007
|
+
* g.addEdge('A', 'B');
|
|
4008
|
+
* g.addEdge('B', 'C');
|
|
4009
|
+
* const result = g.tarjan();
|
|
4010
|
+
* console.log(result); // defined;
|
|
4011
|
+
*/
|
|
3019
4012
|
tarjan() {
|
|
3020
4013
|
const dfnMap = /* @__PURE__ */ new Map();
|
|
3021
4014
|
const lowMap = /* @__PURE__ */ new Map();
|
|
@@ -3063,18 +4056,152 @@ var graphTyped = (() => {
|
|
|
3063
4056
|
};
|
|
3064
4057
|
}
|
|
3065
4058
|
/**
|
|
3066
|
-
*
|
|
3067
|
-
*
|
|
3068
|
-
* @
|
|
4059
|
+
* Find biconnected components using edge-stack Tarjan variant.
|
|
4060
|
+
* A biconnected component is a maximal biconnected subgraph.
|
|
4061
|
+
* @returns Array of edge arrays, each representing a biconnected component.
|
|
4062
|
+
* @remarks Time O(V + E), Space O(V + E)
|
|
3069
4063
|
*/
|
|
4064
|
+
getBiconnectedComponents() {
|
|
4065
|
+
const dfn = /* @__PURE__ */ new Map();
|
|
4066
|
+
const low = /* @__PURE__ */ new Map();
|
|
4067
|
+
const edgeStack = [];
|
|
4068
|
+
const components = [];
|
|
4069
|
+
let time = 0;
|
|
4070
|
+
const dfs = (vertex, parent) => {
|
|
4071
|
+
dfn.set(vertex, time);
|
|
4072
|
+
low.set(vertex, time);
|
|
4073
|
+
time++;
|
|
4074
|
+
const neighbors = this.getNeighbors(vertex);
|
|
4075
|
+
let childCount = 0;
|
|
4076
|
+
for (const neighbor of neighbors) {
|
|
4077
|
+
const edge = this.getEdge(vertex, neighbor);
|
|
4078
|
+
if (!edge) continue;
|
|
4079
|
+
if (!dfn.has(neighbor)) {
|
|
4080
|
+
childCount++;
|
|
4081
|
+
edgeStack.push(edge);
|
|
4082
|
+
dfs(neighbor, vertex);
|
|
4083
|
+
low.set(vertex, Math.min(low.get(vertex), low.get(neighbor)));
|
|
4084
|
+
if (parent === void 0 && childCount > 1 || parent !== void 0 && low.get(neighbor) >= dfn.get(vertex)) {
|
|
4085
|
+
const component = [];
|
|
4086
|
+
let e;
|
|
4087
|
+
do {
|
|
4088
|
+
e = edgeStack.pop();
|
|
4089
|
+
if (e) component.push(e);
|
|
4090
|
+
} while (e && e !== edge);
|
|
4091
|
+
if (component.length > 0) components.push(component);
|
|
4092
|
+
}
|
|
4093
|
+
} else if (neighbor !== parent && dfn.get(neighbor) < dfn.get(vertex)) {
|
|
4094
|
+
edgeStack.push(edge);
|
|
4095
|
+
low.set(vertex, Math.min(low.get(vertex), dfn.get(neighbor)));
|
|
4096
|
+
}
|
|
4097
|
+
}
|
|
4098
|
+
};
|
|
4099
|
+
for (const vertex of this.vertexMap.values()) {
|
|
4100
|
+
if (!dfn.has(vertex)) {
|
|
4101
|
+
dfs(vertex, void 0);
|
|
4102
|
+
if (edgeStack.length > 0) {
|
|
4103
|
+
components.push([...edgeStack]);
|
|
4104
|
+
edgeStack.length = 0;
|
|
4105
|
+
}
|
|
4106
|
+
}
|
|
4107
|
+
}
|
|
4108
|
+
return components;
|
|
4109
|
+
}
|
|
4110
|
+
/**
|
|
4111
|
+
* Detect whether the graph contains a cycle.
|
|
4112
|
+
* Uses DFS with parent tracking.
|
|
4113
|
+
* @returns `true` if a cycle exists, `false` otherwise.
|
|
4114
|
+
* @remarks Time O(V + E), Space O(V)
|
|
4115
|
+
|
|
4116
|
+
|
|
4117
|
+
|
|
4118
|
+
|
|
4119
|
+
|
|
4120
|
+
|
|
4121
|
+
|
|
4122
|
+
|
|
4123
|
+
* @example
|
|
4124
|
+
* // Detect cycle
|
|
4125
|
+
* const g = new UndirectedGraph();
|
|
4126
|
+
* g.addVertex('A');
|
|
4127
|
+
* g.addVertex('B');
|
|
4128
|
+
* g.addVertex('C');
|
|
4129
|
+
* g.addEdge('A', 'B');
|
|
4130
|
+
* g.addEdge('B', 'C');
|
|
4131
|
+
* console.log(g.hasCycle()); // false;
|
|
4132
|
+
* g.addEdge('C', 'A');
|
|
4133
|
+
* console.log(g.hasCycle()); // true;
|
|
4134
|
+
*/
|
|
4135
|
+
hasCycle() {
|
|
4136
|
+
const visited = /* @__PURE__ */ new Set();
|
|
4137
|
+
const dfs = (vertex, parent) => {
|
|
4138
|
+
visited.add(vertex);
|
|
4139
|
+
for (const neighbor of this.getNeighbors(vertex)) {
|
|
4140
|
+
if (!visited.has(neighbor)) {
|
|
4141
|
+
if (dfs(neighbor, vertex)) return true;
|
|
4142
|
+
} else if (neighbor !== parent) {
|
|
4143
|
+
return true;
|
|
4144
|
+
}
|
|
4145
|
+
}
|
|
4146
|
+
return false;
|
|
4147
|
+
};
|
|
4148
|
+
for (const vertex of this.vertexMap.values()) {
|
|
4149
|
+
if (!visited.has(vertex)) {
|
|
4150
|
+
if (dfs(vertex, void 0)) return true;
|
|
4151
|
+
}
|
|
4152
|
+
}
|
|
4153
|
+
return false;
|
|
4154
|
+
}
|
|
4155
|
+
/**
|
|
4156
|
+
* Get bridges discovered by `tarjan()`.
|
|
4157
|
+
* @returns Array of edges that are bridges.
|
|
4158
|
+
* @remarks Time O(B), Space O(1)
|
|
4159
|
+
|
|
4160
|
+
|
|
4161
|
+
|
|
4162
|
+
|
|
4163
|
+
|
|
4164
|
+
|
|
4165
|
+
|
|
4166
|
+
|
|
4167
|
+
* @example
|
|
4168
|
+
* // Find bridge edges
|
|
4169
|
+
* const g = new UndirectedGraph();
|
|
4170
|
+
* g.addVertex('A');
|
|
4171
|
+
* g.addVertex('B');
|
|
4172
|
+
* g.addVertex('C');
|
|
4173
|
+
* g.addEdge('A', 'B');
|
|
4174
|
+
* g.addEdge('B', 'C');
|
|
4175
|
+
* const bridges = g.getBridges();
|
|
4176
|
+
* console.log(bridges.length); // 2;
|
|
4177
|
+
*/
|
|
3070
4178
|
getBridges() {
|
|
3071
4179
|
return this.tarjan().bridges;
|
|
3072
4180
|
}
|
|
3073
4181
|
/**
|
|
3074
|
-
|
|
3075
|
-
|
|
3076
|
-
|
|
3077
|
-
|
|
4182
|
+
* Get articulation points discovered by `tarjan()`.
|
|
4183
|
+
* @returns Array of cut vertices.
|
|
4184
|
+
* @remarks Time O(C), Space O(1)
|
|
4185
|
+
|
|
4186
|
+
|
|
4187
|
+
|
|
4188
|
+
|
|
4189
|
+
|
|
4190
|
+
|
|
4191
|
+
|
|
4192
|
+
|
|
4193
|
+
* @example
|
|
4194
|
+
* // Find articulation points
|
|
4195
|
+
* const g = new UndirectedGraph();
|
|
4196
|
+
* g.addVertex('A');
|
|
4197
|
+
* g.addVertex('B');
|
|
4198
|
+
* g.addVertex('C');
|
|
4199
|
+
* g.addEdge('A', 'B');
|
|
4200
|
+
* g.addEdge('B', 'C');
|
|
4201
|
+
* const cuts = g.getCutVertices();
|
|
4202
|
+
* console.log(cuts.length); // 1;
|
|
4203
|
+
* console.log(cuts[0].key); // 'B';
|
|
4204
|
+
*/
|
|
3078
4205
|
getCutVertices() {
|
|
3079
4206
|
return this.tarjan().cutVertices;
|
|
3080
4207
|
}
|
|
@@ -3205,27 +4332,6 @@ var graphTyped = (() => {
|
|
|
3205
4332
|
return new _MapGraph(oc, br);
|
|
3206
4333
|
}
|
|
3207
4334
|
};
|
|
3208
|
-
|
|
3209
|
-
// src/common/index.ts
|
|
3210
|
-
var DFSOperation = /* @__PURE__ */ ((DFSOperation2) => {
|
|
3211
|
-
DFSOperation2[DFSOperation2["VISIT"] = 0] = "VISIT";
|
|
3212
|
-
DFSOperation2[DFSOperation2["PROCESS"] = 1] = "PROCESS";
|
|
3213
|
-
return DFSOperation2;
|
|
3214
|
-
})(DFSOperation || {});
|
|
3215
|
-
var Range = class {
|
|
3216
|
-
constructor(low, high, includeLow = true, includeHigh = true) {
|
|
3217
|
-
this.low = low;
|
|
3218
|
-
this.high = high;
|
|
3219
|
-
this.includeLow = includeLow;
|
|
3220
|
-
this.includeHigh = includeHigh;
|
|
3221
|
-
}
|
|
3222
|
-
// Determine whether a key is within the range
|
|
3223
|
-
isInRange(key, comparator) {
|
|
3224
|
-
const lowCheck = this.includeLow ? comparator(key, this.low) >= 0 : comparator(key, this.low) > 0;
|
|
3225
|
-
const highCheck = this.includeHigh ? comparator(key, this.high) <= 0 : comparator(key, this.high) < 0;
|
|
3226
|
-
return lowCheck && highCheck;
|
|
3227
|
-
}
|
|
3228
|
-
};
|
|
3229
4335
|
return __toCommonJS(src_exports);
|
|
3230
4336
|
})();
|
|
3231
4337
|
/**
|