graph-typed 2.4.5 → 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 +1112 -201
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/cjs-legacy/index.cjs +1112 -201
- package/dist/cjs-legacy/index.cjs.map +1 -1
- package/dist/esm/index.mjs +1112 -201
- package/dist/esm/index.mjs.map +1 -1
- package/dist/esm-legacy/index.mjs +1112 -201
- package/dist/esm-legacy/index.mjs.map +1 -1
- 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 +429 -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 +212 -32
- 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/directed-graph.d.ts +219 -47
- package/dist/types/data-structures/graph/map-graph.d.ts +59 -1
- package/dist/types/data-structures/graph/undirected-graph.d.ts +204 -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 +272 -65
- 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/umd/graph-typed.js +1112 -201
- package/dist/umd/graph-typed.js.map +1 -1
- package/dist/umd/graph-typed.min.js +2 -2
- package/dist/umd/graph-typed.min.js.map +1 -1
- package/package.json +2 -2
- package/src/data-structures/base/iterable-element-base.ts +4 -5
- package/src/data-structures/binary-tree/avl-tree.ts +134 -51
- package/src/data-structures/binary-tree/binary-indexed-tree.ts +302 -247
- package/src/data-structures/binary-tree/binary-tree.ts +429 -79
- package/src/data-structures/binary-tree/bst.ts +335 -34
- package/src/data-structures/binary-tree/red-black-tree.ts +290 -97
- package/src/data-structures/binary-tree/segment-tree.ts +372 -248
- package/src/data-structures/binary-tree/tree-map.ts +1284 -6
- package/src/data-structures/binary-tree/tree-multi-map.ts +1094 -211
- package/src/data-structures/binary-tree/tree-multi-set.ts +858 -65
- package/src/data-structures/binary-tree/tree-set.ts +1136 -9
- package/src/data-structures/graph/directed-graph.ts +219 -47
- package/src/data-structures/graph/map-graph.ts +59 -1
- package/src/data-structures/graph/undirected-graph.ts +204 -59
- package/src/data-structures/hash/hash-map.ts +230 -77
- package/src/data-structures/heap/heap.ts +287 -99
- package/src/data-structures/heap/max-heap.ts +46 -0
- 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 +416 -12
- package/src/data-structures/priority-queue/max-priority-queue.ts +57 -0
- 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 +272 -65
- 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 +213 -43
- 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/dist/cjs/index.cjs
CHANGED
|
@@ -273,7 +273,7 @@ var IterableElementBase = class {
|
|
|
273
273
|
if (options) {
|
|
274
274
|
const { toElementFn } = options;
|
|
275
275
|
if (typeof toElementFn === "function") this._toElementFn = toElementFn;
|
|
276
|
-
else if (toElementFn) throw new TypeError(
|
|
276
|
+
else if (toElementFn) throw new TypeError("toElementFn must be a function type");
|
|
277
277
|
}
|
|
278
278
|
}
|
|
279
279
|
/**
|
|
@@ -436,7 +436,7 @@ var IterableElementBase = class {
|
|
|
436
436
|
acc = initialValue;
|
|
437
437
|
} else {
|
|
438
438
|
const first = iter.next();
|
|
439
|
-
if (first.done) throw new TypeError(
|
|
439
|
+
if (first.done) throw new TypeError("Reduce of empty structure with no initial value");
|
|
440
440
|
acc = first.value;
|
|
441
441
|
index = 1;
|
|
442
442
|
}
|
|
@@ -509,10 +509,30 @@ var Heap = class _Heap extends IterableElementBase {
|
|
|
509
509
|
return this._elements;
|
|
510
510
|
}
|
|
511
511
|
/**
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
512
|
+
* Get the number of elements.
|
|
513
|
+
* @remarks Time O(1), Space O(1)
|
|
514
|
+
* @returns Heap size.
|
|
515
|
+
|
|
516
|
+
|
|
517
|
+
|
|
518
|
+
|
|
519
|
+
|
|
520
|
+
|
|
521
|
+
|
|
522
|
+
|
|
523
|
+
|
|
524
|
+
|
|
525
|
+
|
|
526
|
+
* @example
|
|
527
|
+
* // Track heap capacity
|
|
528
|
+
* const heap = new Heap<number>();
|
|
529
|
+
* console.log(heap.size); // 0;
|
|
530
|
+
* heap.add(10);
|
|
531
|
+
* heap.add(20);
|
|
532
|
+
* console.log(heap.size); // 2;
|
|
533
|
+
* heap.poll();
|
|
534
|
+
* console.log(heap.size); // 1;
|
|
535
|
+
*/
|
|
516
536
|
get size() {
|
|
517
537
|
return this.elements.length;
|
|
518
538
|
}
|
|
@@ -550,21 +570,61 @@ var Heap = class _Heap extends IterableElementBase {
|
|
|
550
570
|
return new _Heap(elements, options);
|
|
551
571
|
}
|
|
552
572
|
/**
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
573
|
+
* Insert an element.
|
|
574
|
+
* @remarks Time O(1) amortized, Space O(1)
|
|
575
|
+
* @param element - Element to insert.
|
|
576
|
+
* @returns True.
|
|
577
|
+
|
|
578
|
+
|
|
579
|
+
|
|
580
|
+
|
|
581
|
+
|
|
582
|
+
|
|
583
|
+
|
|
584
|
+
|
|
585
|
+
|
|
586
|
+
|
|
587
|
+
|
|
588
|
+
* @example
|
|
589
|
+
* // basic Heap creation and add operation
|
|
590
|
+
* // Create a min heap (default)
|
|
591
|
+
* const minHeap = new Heap([5, 3, 7, 1, 9, 2]);
|
|
592
|
+
*
|
|
593
|
+
* // Verify size
|
|
594
|
+
* console.log(minHeap.size); // 6;
|
|
595
|
+
*
|
|
596
|
+
* // Add new element
|
|
597
|
+
* minHeap.add(4);
|
|
598
|
+
* console.log(minHeap.size); // 7;
|
|
599
|
+
*
|
|
600
|
+
* // Min heap property: smallest element at root
|
|
601
|
+
* const min = minHeap.peek();
|
|
602
|
+
* console.log(min); // 1;
|
|
603
|
+
*/
|
|
558
604
|
add(element) {
|
|
559
605
|
this._elements.push(element);
|
|
560
606
|
return this._bubbleUp(this.elements.length - 1);
|
|
561
607
|
}
|
|
562
608
|
/**
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
609
|
+
* Insert many elements from an iterable.
|
|
610
|
+
* @remarks Time O(N log N), Space O(1)
|
|
611
|
+
* @param elements - Iterable of elements or raw values.
|
|
612
|
+
* @returns Array of per-element success flags.
|
|
613
|
+
|
|
614
|
+
|
|
615
|
+
|
|
616
|
+
|
|
617
|
+
|
|
618
|
+
|
|
619
|
+
|
|
620
|
+
|
|
621
|
+
* @example
|
|
622
|
+
* // Add multiple elements
|
|
623
|
+
* const heap = new Heap<number>([], { comparator: (a, b) => a - b });
|
|
624
|
+
* heap.addMany([5, 3, 7, 1]);
|
|
625
|
+
* console.log(heap.peek()); // 1;
|
|
626
|
+
* console.log(heap.size); // 4;
|
|
627
|
+
*/
|
|
568
628
|
addMany(elements) {
|
|
569
629
|
const flags = [];
|
|
570
630
|
for (const el of elements) {
|
|
@@ -579,10 +639,46 @@ var Heap = class _Heap extends IterableElementBase {
|
|
|
579
639
|
return flags;
|
|
580
640
|
}
|
|
581
641
|
/**
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
642
|
+
* Remove and return the top element.
|
|
643
|
+
* @remarks Time O(log N), Space O(1)
|
|
644
|
+
* @returns Top element or undefined.
|
|
645
|
+
|
|
646
|
+
|
|
647
|
+
|
|
648
|
+
|
|
649
|
+
|
|
650
|
+
|
|
651
|
+
|
|
652
|
+
|
|
653
|
+
|
|
654
|
+
|
|
655
|
+
|
|
656
|
+
* @example
|
|
657
|
+
* // Heap with custom comparator (MaxHeap behavior)
|
|
658
|
+
* interface Task {
|
|
659
|
+
* id: number;
|
|
660
|
+
* priority: number;
|
|
661
|
+
* name: string;
|
|
662
|
+
* }
|
|
663
|
+
*
|
|
664
|
+
* // Custom comparator for max heap behavior (higher priority first)
|
|
665
|
+
* const tasks: Task[] = [
|
|
666
|
+
* { id: 1, priority: 5, name: 'Email' },
|
|
667
|
+
* { id: 2, priority: 3, name: 'Chat' },
|
|
668
|
+
* { id: 3, priority: 8, name: 'Alert' }
|
|
669
|
+
* ];
|
|
670
|
+
*
|
|
671
|
+
* const maxHeap = new Heap(tasks, {
|
|
672
|
+
* comparator: (a: Task, b: Task) => b.priority - a.priority
|
|
673
|
+
* });
|
|
674
|
+
*
|
|
675
|
+
* console.log(maxHeap.size); // 3;
|
|
676
|
+
*
|
|
677
|
+
* // Peek returns highest priority task
|
|
678
|
+
* const topTask = maxHeap.peek();
|
|
679
|
+
* console.log(topTask?.priority); // 8;
|
|
680
|
+
* console.log(topTask?.name); // 'Alert';
|
|
681
|
+
*/
|
|
586
682
|
poll() {
|
|
587
683
|
if (this.elements.length === 0) return;
|
|
588
684
|
const value = this.elements[0];
|
|
@@ -594,26 +690,125 @@ var Heap = class _Heap extends IterableElementBase {
|
|
|
594
690
|
return value;
|
|
595
691
|
}
|
|
596
692
|
/**
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
693
|
+
* Get the current top element without removing it.
|
|
694
|
+
* @remarks Time O(1), Space O(1)
|
|
695
|
+
* @returns Top element or undefined.
|
|
696
|
+
|
|
697
|
+
|
|
698
|
+
|
|
699
|
+
|
|
700
|
+
|
|
701
|
+
|
|
702
|
+
|
|
703
|
+
|
|
704
|
+
|
|
705
|
+
|
|
706
|
+
|
|
707
|
+
* @example
|
|
708
|
+
* // Heap for event processing with priority
|
|
709
|
+
* interface Event {
|
|
710
|
+
* id: number;
|
|
711
|
+
* type: 'critical' | 'warning' | 'info';
|
|
712
|
+
* timestamp: number;
|
|
713
|
+
* message: string;
|
|
714
|
+
* }
|
|
715
|
+
*
|
|
716
|
+
* // Custom priority: critical > warning > info
|
|
717
|
+
* const priorityMap = { critical: 3, warning: 2, info: 1 };
|
|
718
|
+
*
|
|
719
|
+
* const eventHeap = new Heap<Event>([], {
|
|
720
|
+
* comparator: (a: Event, b: Event) => {
|
|
721
|
+
* const priorityA = priorityMap[a.type];
|
|
722
|
+
* const priorityB = priorityMap[b.type];
|
|
723
|
+
* return priorityB - priorityA; // Higher priority first
|
|
724
|
+
* }
|
|
725
|
+
* });
|
|
726
|
+
*
|
|
727
|
+
* // Add events in random order
|
|
728
|
+
* eventHeap.add({ id: 1, type: 'info', timestamp: 100, message: 'User logged in' });
|
|
729
|
+
* eventHeap.add({ id: 2, type: 'critical', timestamp: 101, message: 'Server down' });
|
|
730
|
+
* eventHeap.add({ id: 3, type: 'warning', timestamp: 102, message: 'High memory' });
|
|
731
|
+
* eventHeap.add({ id: 4, type: 'info', timestamp: 103, message: 'Cache cleared' });
|
|
732
|
+
* eventHeap.add({ id: 5, type: 'critical', timestamp: 104, message: 'Database error' });
|
|
733
|
+
*
|
|
734
|
+
* console.log(eventHeap.size); // 5;
|
|
735
|
+
*
|
|
736
|
+
* // Process events by priority (critical first)
|
|
737
|
+
* const processedOrder: Event[] = [];
|
|
738
|
+
* while (eventHeap.size > 0) {
|
|
739
|
+
* const event = eventHeap.poll();
|
|
740
|
+
* if (event) {
|
|
741
|
+
* processedOrder.push(event);
|
|
742
|
+
* }
|
|
743
|
+
* }
|
|
744
|
+
*
|
|
745
|
+
* // Verify critical events came first
|
|
746
|
+
* console.log(processedOrder[0].type); // 'critical';
|
|
747
|
+
* console.log(processedOrder[1].type); // 'critical';
|
|
748
|
+
* console.log(processedOrder[2].type); // 'warning';
|
|
749
|
+
* console.log(processedOrder[3].type); // 'info';
|
|
750
|
+
* console.log(processedOrder[4].type); // 'info';
|
|
751
|
+
*
|
|
752
|
+
* // Verify O(log n) operations
|
|
753
|
+
* const newHeap = new Heap<number>([5, 3, 7, 1]);
|
|
754
|
+
*
|
|
755
|
+
* // Add - O(log n)
|
|
756
|
+
* newHeap.add(2);
|
|
757
|
+
* console.log(newHeap.size); // 5;
|
|
758
|
+
*
|
|
759
|
+
* // Poll - O(log n)
|
|
760
|
+
* const removed = newHeap.poll();
|
|
761
|
+
* console.log(removed); // 1;
|
|
762
|
+
*
|
|
763
|
+
* // Peek - O(1)
|
|
764
|
+
* const top = newHeap.peek();
|
|
765
|
+
* console.log(top); // 2;
|
|
766
|
+
*/
|
|
601
767
|
peek() {
|
|
602
768
|
return this.elements[0];
|
|
603
769
|
}
|
|
604
770
|
/**
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
771
|
+
* Check whether the heap is empty.
|
|
772
|
+
* @remarks Time O(1), Space O(1)
|
|
773
|
+
* @returns True if size is 0.
|
|
774
|
+
|
|
775
|
+
|
|
776
|
+
|
|
777
|
+
|
|
778
|
+
|
|
779
|
+
|
|
780
|
+
|
|
781
|
+
|
|
782
|
+
|
|
783
|
+
* @example
|
|
784
|
+
* // Check if heap is empty
|
|
785
|
+
* const heap = new Heap<number>([], { comparator: (a, b) => a - b });
|
|
786
|
+
* console.log(heap.isEmpty()); // true;
|
|
787
|
+
* heap.add(1);
|
|
788
|
+
* console.log(heap.isEmpty()); // false;
|
|
789
|
+
*/
|
|
609
790
|
isEmpty() {
|
|
610
791
|
return this.size === 0;
|
|
611
792
|
}
|
|
612
793
|
/**
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
794
|
+
* Remove all elements.
|
|
795
|
+
* @remarks Time O(1), Space O(1)
|
|
796
|
+
* @returns void
|
|
797
|
+
|
|
798
|
+
|
|
799
|
+
|
|
800
|
+
|
|
801
|
+
|
|
802
|
+
|
|
803
|
+
|
|
804
|
+
|
|
805
|
+
|
|
806
|
+
* @example
|
|
807
|
+
* // Remove all elements
|
|
808
|
+
* const heap = new Heap<number>([1, 2, 3], { comparator: (a, b) => a - b });
|
|
809
|
+
* heap.clear();
|
|
810
|
+
* console.log(heap.isEmpty()); // true;
|
|
811
|
+
*/
|
|
617
812
|
clear() {
|
|
618
813
|
this._elements = [];
|
|
619
814
|
}
|
|
@@ -628,21 +823,41 @@ var Heap = class _Heap extends IterableElementBase {
|
|
|
628
823
|
return this.fix();
|
|
629
824
|
}
|
|
630
825
|
/**
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
826
|
+
* Check if an equal element exists in the heap.
|
|
827
|
+
* @remarks Time O(N), Space O(1)
|
|
828
|
+
* @param element - Element to search for.
|
|
829
|
+
* @returns True if found.
|
|
830
|
+
|
|
831
|
+
|
|
832
|
+
* @example
|
|
833
|
+
* // Check element existence
|
|
834
|
+
* const heap = new Heap<number>([3, 1, 2], { comparator: (a, b) => a - b });
|
|
835
|
+
* console.log(heap.has(1)); // true;
|
|
836
|
+
* console.log(heap.has(99)); // false;
|
|
837
|
+
*/
|
|
636
838
|
has(element) {
|
|
637
839
|
for (const el of this.elements) if (this._equals(el, element)) return true;
|
|
638
840
|
return false;
|
|
639
841
|
}
|
|
640
842
|
/**
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
843
|
+
* Delete one occurrence of an element.
|
|
844
|
+
* @remarks Time O(N), Space O(1)
|
|
845
|
+
* @param element - Element to delete.
|
|
846
|
+
* @returns True if an element was removed.
|
|
847
|
+
|
|
848
|
+
|
|
849
|
+
|
|
850
|
+
|
|
851
|
+
|
|
852
|
+
|
|
853
|
+
|
|
854
|
+
|
|
855
|
+
* @example
|
|
856
|
+
* // Remove specific element
|
|
857
|
+
* const heap = new Heap<number>([3, 1, 4, 1, 5], { comparator: (a, b) => a - b });
|
|
858
|
+
* heap.delete(4);
|
|
859
|
+
* console.log(heap.toArray().includes(4)); // false;
|
|
860
|
+
*/
|
|
646
861
|
delete(element) {
|
|
647
862
|
let index = -1;
|
|
648
863
|
for (let i = 0; i < this.elements.length; i++) {
|
|
@@ -700,11 +915,18 @@ var Heap = class _Heap extends IterableElementBase {
|
|
|
700
915
|
return this;
|
|
701
916
|
}
|
|
702
917
|
/**
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
918
|
+
* Traverse the binary heap as a complete binary tree and collect elements.
|
|
919
|
+
* @remarks Time O(N), Space O(H)
|
|
920
|
+
* @param [order] - Traversal order: 'PRE' | 'IN' | 'POST'.
|
|
921
|
+
* @returns Array of visited elements.
|
|
922
|
+
|
|
923
|
+
|
|
924
|
+
* @example
|
|
925
|
+
* // Depth-first traversal
|
|
926
|
+
* const heap = new Heap<number>([3, 1, 2], { comparator: (a, b) => a - b });
|
|
927
|
+
* const result = heap.dfs('IN');
|
|
928
|
+
* console.log(result.length); // 3;
|
|
929
|
+
*/
|
|
708
930
|
dfs(order = "PRE") {
|
|
709
931
|
const result = [];
|
|
710
932
|
const _dfs = /* @__PURE__ */ __name((index) => {
|
|
@@ -741,10 +963,26 @@ var Heap = class _Heap extends IterableElementBase {
|
|
|
741
963
|
return results;
|
|
742
964
|
}
|
|
743
965
|
/**
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
966
|
+
* Return all elements in ascending order by repeatedly polling.
|
|
967
|
+
* @remarks Time O(N log N), Space O(N)
|
|
968
|
+
* @returns Sorted array of elements.
|
|
969
|
+
|
|
970
|
+
|
|
971
|
+
|
|
972
|
+
|
|
973
|
+
|
|
974
|
+
|
|
975
|
+
|
|
976
|
+
|
|
977
|
+
|
|
978
|
+
|
|
979
|
+
|
|
980
|
+
* @example
|
|
981
|
+
* // Sort elements using heap
|
|
982
|
+
* const heap = new Heap<number>([5, 1, 3, 2, 4]);
|
|
983
|
+
* const sorted = heap.sort();
|
|
984
|
+
* console.log(sorted); // [1, 2, 3, 4, 5];
|
|
985
|
+
*/
|
|
748
986
|
sort() {
|
|
749
987
|
const visited = [];
|
|
750
988
|
const cloned = this._createInstance();
|
|
@@ -756,22 +994,52 @@ var Heap = class _Heap extends IterableElementBase {
|
|
|
756
994
|
return visited;
|
|
757
995
|
}
|
|
758
996
|
/**
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
997
|
+
* Deep clone this heap.
|
|
998
|
+
* @remarks Time O(N), Space O(N)
|
|
999
|
+
* @returns A new heap with the same elements.
|
|
1000
|
+
|
|
1001
|
+
|
|
1002
|
+
|
|
1003
|
+
|
|
1004
|
+
|
|
1005
|
+
|
|
1006
|
+
|
|
1007
|
+
|
|
1008
|
+
|
|
1009
|
+
* @example
|
|
1010
|
+
* // Create independent copy
|
|
1011
|
+
* const heap = new Heap<number>([3, 1, 4], { comparator: (a, b) => a - b });
|
|
1012
|
+
* const copy = heap.clone();
|
|
1013
|
+
* copy.poll();
|
|
1014
|
+
* console.log(heap.size); // 3;
|
|
1015
|
+
* console.log(copy.size); // 2;
|
|
1016
|
+
*/
|
|
763
1017
|
clone() {
|
|
764
1018
|
const next = this._createInstance();
|
|
765
1019
|
for (const x of this.elements) next.add(x);
|
|
766
1020
|
return next;
|
|
767
1021
|
}
|
|
768
1022
|
/**
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
1023
|
+
* Filter elements into a new heap of the same class.
|
|
1024
|
+
* @remarks Time O(N log N), Space O(N)
|
|
1025
|
+
* @param callback - Predicate (element, index, heap) → boolean to keep element.
|
|
1026
|
+
* @param [thisArg] - Value for `this` inside the callback.
|
|
1027
|
+
* @returns A new heap with the kept elements.
|
|
1028
|
+
|
|
1029
|
+
|
|
1030
|
+
|
|
1031
|
+
|
|
1032
|
+
|
|
1033
|
+
|
|
1034
|
+
|
|
1035
|
+
|
|
1036
|
+
|
|
1037
|
+
* @example
|
|
1038
|
+
* // Filter elements
|
|
1039
|
+
* const heap = new Heap<number>([1, 2, 3, 4, 5], { comparator: (a, b) => a - b });
|
|
1040
|
+
* const evens = heap.filter(x => x % 2 === 0);
|
|
1041
|
+
* console.log(evens.size); // 2;
|
|
1042
|
+
*/
|
|
775
1043
|
filter(callback, thisArg) {
|
|
776
1044
|
const out = this._createInstance();
|
|
777
1045
|
let i = 0;
|
|
@@ -785,15 +1053,28 @@ var Heap = class _Heap extends IterableElementBase {
|
|
|
785
1053
|
return out;
|
|
786
1054
|
}
|
|
787
1055
|
/**
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
1056
|
+
* Map elements into a new heap of possibly different element type.
|
|
1057
|
+
* @remarks Time O(N log N), Space O(N)
|
|
1058
|
+
* @template EM
|
|
1059
|
+
* @template RM
|
|
1060
|
+
* @param callback - Mapping function (element, index, heap) → newElement.
|
|
1061
|
+
* @param options - Options for the output heap, including comparator for EM.
|
|
1062
|
+
* @param [thisArg] - Value for `this` inside the callback.
|
|
1063
|
+
* @returns A new heap with mapped elements.
|
|
1064
|
+
|
|
1065
|
+
|
|
1066
|
+
|
|
1067
|
+
|
|
1068
|
+
|
|
1069
|
+
|
|
1070
|
+
|
|
1071
|
+
|
|
1072
|
+
* @example
|
|
1073
|
+
* // Transform elements
|
|
1074
|
+
* const heap = new Heap<number>([1, 2, 3], { comparator: (a, b) => a - b });
|
|
1075
|
+
* const doubled = heap.map(x => x * 2, { comparator: (a, b) => a - b });
|
|
1076
|
+
* console.log(doubled.peek()); // 2;
|
|
1077
|
+
*/
|
|
797
1078
|
map(callback, options, thisArg) {
|
|
798
1079
|
const { comparator, toElementFn, ...rest } = options ?? {};
|
|
799
1080
|
if (!comparator) throw new TypeError(ERR.comparatorRequired("Heap.map"));
|
|
@@ -1156,18 +1437,52 @@ var Queue = class _Queue extends LinearBase {
|
|
|
1156
1437
|
this._autoCompactRatio = value;
|
|
1157
1438
|
}
|
|
1158
1439
|
/**
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1440
|
+
* Get the number of elements currently in the queue.
|
|
1441
|
+
* @remarks Time O(1), Space O(1)
|
|
1442
|
+
* @returns Current length.
|
|
1443
|
+
|
|
1444
|
+
|
|
1445
|
+
|
|
1446
|
+
|
|
1447
|
+
|
|
1448
|
+
|
|
1449
|
+
|
|
1450
|
+
|
|
1451
|
+
|
|
1452
|
+
|
|
1453
|
+
|
|
1454
|
+
* @example
|
|
1455
|
+
* // Track queue length
|
|
1456
|
+
* const q = new Queue<number>();
|
|
1457
|
+
* console.log(q.length); // 0;
|
|
1458
|
+
* q.push(1);
|
|
1459
|
+
* q.push(2);
|
|
1460
|
+
* console.log(q.length); // 2;
|
|
1461
|
+
*/
|
|
1163
1462
|
get length() {
|
|
1164
1463
|
return this.elements.length - this._offset;
|
|
1165
1464
|
}
|
|
1166
1465
|
/**
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1466
|
+
* Get the first element (front) without removing it.
|
|
1467
|
+
* @remarks Time O(1), Space O(1)
|
|
1468
|
+
* @returns Front element or undefined.
|
|
1469
|
+
|
|
1470
|
+
|
|
1471
|
+
|
|
1472
|
+
|
|
1473
|
+
|
|
1474
|
+
|
|
1475
|
+
|
|
1476
|
+
|
|
1477
|
+
|
|
1478
|
+
|
|
1479
|
+
|
|
1480
|
+
* @example
|
|
1481
|
+
* // View the front element
|
|
1482
|
+
* const q = new Queue<string>(['first', 'second', 'third']);
|
|
1483
|
+
* console.log(q.first); // 'first';
|
|
1484
|
+
* console.log(q.length); // 3;
|
|
1485
|
+
*/
|
|
1171
1486
|
get first() {
|
|
1172
1487
|
return this.length > 0 ? this.elements[this._offset] : void 0;
|
|
1173
1488
|
}
|
|
@@ -1190,19 +1505,69 @@ var Queue = class _Queue extends LinearBase {
|
|
|
1190
1505
|
return new _Queue(elements);
|
|
1191
1506
|
}
|
|
1192
1507
|
/**
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1508
|
+
* Check whether the queue is empty.
|
|
1509
|
+
* @remarks Time O(1), Space O(1)
|
|
1510
|
+
* @returns True if length is 0.
|
|
1511
|
+
|
|
1512
|
+
|
|
1513
|
+
|
|
1514
|
+
|
|
1515
|
+
|
|
1516
|
+
|
|
1517
|
+
|
|
1518
|
+
|
|
1519
|
+
|
|
1520
|
+
|
|
1521
|
+
|
|
1522
|
+
* @example
|
|
1523
|
+
* // Queue for...of iteration and isEmpty check
|
|
1524
|
+
* const queue = new Queue<string>(['A', 'B', 'C', 'D']);
|
|
1525
|
+
*
|
|
1526
|
+
* const elements: string[] = [];
|
|
1527
|
+
* for (const item of queue) {
|
|
1528
|
+
* elements.push(item);
|
|
1529
|
+
* }
|
|
1530
|
+
*
|
|
1531
|
+
* // Verify all elements are iterated in order
|
|
1532
|
+
* console.log(elements); // ['A', 'B', 'C', 'D'];
|
|
1533
|
+
*
|
|
1534
|
+
* // Process all elements
|
|
1535
|
+
* while (queue.length > 0) {
|
|
1536
|
+
* queue.shift();
|
|
1537
|
+
* }
|
|
1538
|
+
*
|
|
1539
|
+
* console.log(queue.length); // 0;
|
|
1540
|
+
*/
|
|
1197
1541
|
isEmpty() {
|
|
1198
1542
|
return this.length === 0;
|
|
1199
1543
|
}
|
|
1200
1544
|
/**
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1545
|
+
* Enqueue one element at the back.
|
|
1546
|
+
* @remarks Time O(1), Space O(1)
|
|
1547
|
+
* @param element - Element to enqueue.
|
|
1548
|
+
* @returns True on success.
|
|
1549
|
+
|
|
1550
|
+
|
|
1551
|
+
|
|
1552
|
+
|
|
1553
|
+
|
|
1554
|
+
|
|
1555
|
+
|
|
1556
|
+
|
|
1557
|
+
|
|
1558
|
+
|
|
1559
|
+
|
|
1560
|
+
* @example
|
|
1561
|
+
* // basic Queue creation and push operation
|
|
1562
|
+
* // Create a simple Queue with initial values
|
|
1563
|
+
* const queue = new Queue([1, 2, 3, 4, 5]);
|
|
1564
|
+
*
|
|
1565
|
+
* // Verify the queue maintains insertion order
|
|
1566
|
+
* console.log([...queue]); // [1, 2, 3, 4, 5];
|
|
1567
|
+
*
|
|
1568
|
+
* // Check length
|
|
1569
|
+
* console.log(queue.length); // 5;
|
|
1570
|
+
*/
|
|
1206
1571
|
push(element) {
|
|
1207
1572
|
this.elements.push(element);
|
|
1208
1573
|
if (this._maxLen > 0 && this.length > this._maxLen) this.shift();
|
|
@@ -1223,10 +1588,35 @@ var Queue = class _Queue extends LinearBase {
|
|
|
1223
1588
|
return ans;
|
|
1224
1589
|
}
|
|
1225
1590
|
/**
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1591
|
+
* Dequeue one element from the front (amortized via offset).
|
|
1592
|
+
* @remarks Time O(1) amortized, Space O(1)
|
|
1593
|
+
* @returns Removed element or undefined.
|
|
1594
|
+
|
|
1595
|
+
|
|
1596
|
+
|
|
1597
|
+
|
|
1598
|
+
|
|
1599
|
+
|
|
1600
|
+
|
|
1601
|
+
|
|
1602
|
+
|
|
1603
|
+
|
|
1604
|
+
|
|
1605
|
+
* @example
|
|
1606
|
+
* // Queue shift and peek operations
|
|
1607
|
+
* const queue = new Queue<number>([10, 20, 30, 40]);
|
|
1608
|
+
*
|
|
1609
|
+
* // Peek at the front element without removing it
|
|
1610
|
+
* console.log(queue.first); // 10;
|
|
1611
|
+
*
|
|
1612
|
+
* // Remove and get the first element (FIFO)
|
|
1613
|
+
* const first = queue.shift();
|
|
1614
|
+
* console.log(first); // 10;
|
|
1615
|
+
*
|
|
1616
|
+
* // Verify remaining elements and length decreased
|
|
1617
|
+
* console.log([...queue]); // [20, 30, 40];
|
|
1618
|
+
* console.log(queue.length); // 3;
|
|
1619
|
+
*/
|
|
1230
1620
|
shift() {
|
|
1231
1621
|
if (this.length === 0) return void 0;
|
|
1232
1622
|
const first = this.first;
|
|
@@ -1235,11 +1625,24 @@ var Queue = class _Queue extends LinearBase {
|
|
|
1235
1625
|
return first;
|
|
1236
1626
|
}
|
|
1237
1627
|
/**
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1628
|
+
* Delete the first occurrence of a specific element.
|
|
1629
|
+
* @remarks Time O(N), Space O(1)
|
|
1630
|
+
* @param element - Element to remove (strict equality via Object.is).
|
|
1631
|
+
* @returns True if an element was removed.
|
|
1632
|
+
|
|
1633
|
+
|
|
1634
|
+
|
|
1635
|
+
|
|
1636
|
+
|
|
1637
|
+
|
|
1638
|
+
|
|
1639
|
+
|
|
1640
|
+
* @example
|
|
1641
|
+
* // Remove specific element
|
|
1642
|
+
* const q = new Queue<number>([1, 2, 3, 2]);
|
|
1643
|
+
* q.delete(2);
|
|
1644
|
+
* console.log(q.length); // 3;
|
|
1645
|
+
*/
|
|
1243
1646
|
delete(element) {
|
|
1244
1647
|
for (let i = this._offset; i < this.elements.length; i++) {
|
|
1245
1648
|
if (Object.is(this.elements[i], element)) {
|
|
@@ -1250,11 +1653,24 @@ var Queue = class _Queue extends LinearBase {
|
|
|
1250
1653
|
return false;
|
|
1251
1654
|
}
|
|
1252
1655
|
/**
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
|
|
1656
|
+
* Get the element at a given logical index.
|
|
1657
|
+
* @remarks Time O(1), Space O(1)
|
|
1658
|
+
* @param index - Zero-based index from the front.
|
|
1659
|
+
* @returns Element or undefined.
|
|
1660
|
+
|
|
1661
|
+
|
|
1662
|
+
|
|
1663
|
+
|
|
1664
|
+
|
|
1665
|
+
|
|
1666
|
+
|
|
1667
|
+
|
|
1668
|
+
* @example
|
|
1669
|
+
* // Access element by index
|
|
1670
|
+
* const q = new Queue<string>(['a', 'b', 'c']);
|
|
1671
|
+
* console.log(q.at(0)); // 'a';
|
|
1672
|
+
* console.log(q.at(2)); // 'c';
|
|
1673
|
+
*/
|
|
1258
1674
|
at(index) {
|
|
1259
1675
|
if (index < 0 || index >= this.length) return void 0;
|
|
1260
1676
|
return this._elements[this._offset + index];
|
|
@@ -1306,19 +1722,48 @@ var Queue = class _Queue extends LinearBase {
|
|
|
1306
1722
|
return this;
|
|
1307
1723
|
}
|
|
1308
1724
|
/**
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
|
|
1725
|
+
* Remove all elements and reset offset.
|
|
1726
|
+
* @remarks Time O(1), Space O(1)
|
|
1727
|
+
* @returns void
|
|
1728
|
+
|
|
1729
|
+
|
|
1730
|
+
|
|
1731
|
+
|
|
1732
|
+
|
|
1733
|
+
|
|
1734
|
+
|
|
1735
|
+
|
|
1736
|
+
|
|
1737
|
+
* @example
|
|
1738
|
+
* // Remove all elements
|
|
1739
|
+
* const q = new Queue<number>([1, 2, 3]);
|
|
1740
|
+
* q.clear();
|
|
1741
|
+
* console.log(q.length); // 0;
|
|
1742
|
+
*/
|
|
1313
1743
|
clear() {
|
|
1314
1744
|
this._elements = [];
|
|
1315
1745
|
this._offset = 0;
|
|
1316
1746
|
}
|
|
1317
1747
|
/**
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
|
|
1748
|
+
* Compact storage by discarding consumed head elements.
|
|
1749
|
+
* @remarks Time O(N), Space O(N)
|
|
1750
|
+
* @returns True when compaction performed.
|
|
1751
|
+
|
|
1752
|
+
|
|
1753
|
+
|
|
1754
|
+
|
|
1755
|
+
|
|
1756
|
+
|
|
1757
|
+
|
|
1758
|
+
|
|
1759
|
+
* @example
|
|
1760
|
+
* // Reclaim unused memory
|
|
1761
|
+
* const q = new Queue<number>([1, 2, 3, 4, 5]);
|
|
1762
|
+
* q.shift();
|
|
1763
|
+
* q.shift();
|
|
1764
|
+
* q.compact();
|
|
1765
|
+
* console.log(q.length); // 3;
|
|
1766
|
+
*/
|
|
1322
1767
|
compact() {
|
|
1323
1768
|
this._elements = this.elements.slice(this._offset);
|
|
1324
1769
|
this._offset = 0;
|
|
@@ -1344,10 +1789,26 @@ var Queue = class _Queue extends LinearBase {
|
|
|
1344
1789
|
return removed;
|
|
1345
1790
|
}
|
|
1346
1791
|
/**
|
|
1347
|
-
|
|
1348
|
-
|
|
1349
|
-
|
|
1350
|
-
|
|
1792
|
+
* Deep clone this queue and its parameters.
|
|
1793
|
+
* @remarks Time O(N), Space O(N)
|
|
1794
|
+
* @returns A new queue with the same content and options.
|
|
1795
|
+
|
|
1796
|
+
|
|
1797
|
+
|
|
1798
|
+
|
|
1799
|
+
|
|
1800
|
+
|
|
1801
|
+
|
|
1802
|
+
|
|
1803
|
+
|
|
1804
|
+
* @example
|
|
1805
|
+
* // Create independent copy
|
|
1806
|
+
* const q = new Queue<number>([1, 2, 3]);
|
|
1807
|
+
* const copy = q.clone();
|
|
1808
|
+
* copy.shift();
|
|
1809
|
+
* console.log(q.length); // 3;
|
|
1810
|
+
* console.log(copy.length); // 2;
|
|
1811
|
+
*/
|
|
1351
1812
|
clone() {
|
|
1352
1813
|
const out = this._createInstance({ toElementFn: this.toElementFn, maxLen: this._maxLen });
|
|
1353
1814
|
out._setAutoCompactRatio(this._autoCompactRatio);
|
|
@@ -1355,12 +1816,26 @@ var Queue = class _Queue extends LinearBase {
|
|
|
1355
1816
|
return out;
|
|
1356
1817
|
}
|
|
1357
1818
|
/**
|
|
1358
|
-
|
|
1359
|
-
|
|
1360
|
-
|
|
1361
|
-
|
|
1362
|
-
|
|
1363
|
-
|
|
1819
|
+
* Filter elements into a new queue of the same class.
|
|
1820
|
+
* @remarks Time O(N), Space O(N)
|
|
1821
|
+
* @param predicate - Predicate (element, index, queue) → boolean to keep element.
|
|
1822
|
+
* @param [thisArg] - Value for `this` inside the predicate.
|
|
1823
|
+
* @returns A new queue with kept elements.
|
|
1824
|
+
|
|
1825
|
+
|
|
1826
|
+
|
|
1827
|
+
|
|
1828
|
+
|
|
1829
|
+
|
|
1830
|
+
|
|
1831
|
+
|
|
1832
|
+
|
|
1833
|
+
* @example
|
|
1834
|
+
* // Filter elements
|
|
1835
|
+
* const q = new Queue<number>([1, 2, 3, 4, 5]);
|
|
1836
|
+
* const evens = q.filter(x => x % 2 === 0);
|
|
1837
|
+
* console.log(evens.length); // 2;
|
|
1838
|
+
*/
|
|
1364
1839
|
filter(predicate, thisArg) {
|
|
1365
1840
|
const out = this._createInstance({ toElementFn: this.toElementFn, maxLen: this._maxLen });
|
|
1366
1841
|
out._setAutoCompactRatio(this._autoCompactRatio);
|
|
@@ -1372,15 +1847,28 @@ var Queue = class _Queue extends LinearBase {
|
|
|
1372
1847
|
return out;
|
|
1373
1848
|
}
|
|
1374
1849
|
/**
|
|
1375
|
-
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
1850
|
+
* Map each element to a new element in a possibly different-typed queue.
|
|
1851
|
+
* @remarks Time O(N), Space O(N)
|
|
1852
|
+
* @template EM
|
|
1853
|
+
* @template RM
|
|
1854
|
+
* @param callback - Mapping function (element, index, queue) → newElement.
|
|
1855
|
+
* @param [options] - Options for the output queue (e.g., toElementFn, maxLen, autoCompactRatio).
|
|
1856
|
+
* @param [thisArg] - Value for `this` inside the callback.
|
|
1857
|
+
* @returns A new Queue with mapped elements.
|
|
1858
|
+
|
|
1859
|
+
|
|
1860
|
+
|
|
1861
|
+
|
|
1862
|
+
|
|
1863
|
+
|
|
1864
|
+
|
|
1865
|
+
|
|
1866
|
+
* @example
|
|
1867
|
+
* // Transform elements
|
|
1868
|
+
* const q = new Queue<number>([1, 2, 3]);
|
|
1869
|
+
* const doubled = q.map(x => x * 2);
|
|
1870
|
+
* console.log(doubled.toArray()); // [2, 4, 6];
|
|
1871
|
+
*/
|
|
1384
1872
|
map(callback, options, thisArg) {
|
|
1385
1873
|
const out = new this.constructor([], {
|
|
1386
1874
|
toElementFn: options?.toElementFn,
|
|
@@ -2477,12 +2965,28 @@ var DirectedGraph = class _DirectedGraph extends AbstractGraph {
|
|
|
2477
2965
|
return new DirectedEdge(src, dest, weight ?? this.options.defaultEdgeWeight ?? 1, value);
|
|
2478
2966
|
}
|
|
2479
2967
|
/**
|
|
2480
|
-
|
|
2481
|
-
|
|
2482
|
-
|
|
2483
|
-
|
|
2484
|
-
|
|
2485
|
-
|
|
2968
|
+
* Get the unique edge from `src` to `dest`, if present.
|
|
2969
|
+
* @param srcOrKey - Source vertex or key.
|
|
2970
|
+
* @param destOrKey - Destination vertex or key.
|
|
2971
|
+
* @returns Edge instance or `undefined`.
|
|
2972
|
+
* @remarks Time O(1) avg, Space O(1)
|
|
2973
|
+
|
|
2974
|
+
|
|
2975
|
+
|
|
2976
|
+
|
|
2977
|
+
|
|
2978
|
+
|
|
2979
|
+
|
|
2980
|
+
|
|
2981
|
+
* @example
|
|
2982
|
+
* // Get edge between vertices
|
|
2983
|
+
* const g = new DirectedGraph();
|
|
2984
|
+
* g.addVertex('A');
|
|
2985
|
+
* g.addVertex('B');
|
|
2986
|
+
* g.addEdge('A', 'B', 5);
|
|
2987
|
+
* const edge = g.getEdge('A', 'B');
|
|
2988
|
+
* console.log(edge?.weight); // 5;
|
|
2989
|
+
*/
|
|
2486
2990
|
getEdge(srcOrKey, destOrKey) {
|
|
2487
2991
|
let edgeMap = [];
|
|
2488
2992
|
if (srcOrKey !== void 0 && destOrKey !== void 0) {
|
|
@@ -2522,12 +3026,48 @@ var DirectedGraph = class _DirectedGraph extends AbstractGraph {
|
|
|
2522
3026
|
return removed;
|
|
2523
3027
|
}
|
|
2524
3028
|
/**
|
|
2525
|
-
|
|
2526
|
-
|
|
2527
|
-
|
|
2528
|
-
|
|
2529
|
-
|
|
2530
|
-
|
|
3029
|
+
* Delete an edge by instance or by `(srcKey, destKey)`.
|
|
3030
|
+
* @param edgeOrSrcVertexKey - Edge instance or source vertex/key.
|
|
3031
|
+
* @param destVertexKey - Optional destination vertex/key when deleting by pair.
|
|
3032
|
+
* @returns Removed edge or `undefined`.
|
|
3033
|
+
* @remarks Time O(1) avg, Space O(1)
|
|
3034
|
+
|
|
3035
|
+
|
|
3036
|
+
|
|
3037
|
+
|
|
3038
|
+
|
|
3039
|
+
|
|
3040
|
+
|
|
3041
|
+
|
|
3042
|
+
|
|
3043
|
+
|
|
3044
|
+
|
|
3045
|
+
* @example
|
|
3046
|
+
* // DirectedGraph deleteEdge and vertex operations
|
|
3047
|
+
* const graph = new DirectedGraph<string>();
|
|
3048
|
+
*
|
|
3049
|
+
* // Build a small graph
|
|
3050
|
+
* graph.addVertex('X');
|
|
3051
|
+
* graph.addVertex('Y');
|
|
3052
|
+
* graph.addVertex('Z');
|
|
3053
|
+
* graph.addEdge('X', 'Y', 1);
|
|
3054
|
+
* graph.addEdge('Y', 'Z', 2);
|
|
3055
|
+
*
|
|
3056
|
+
* // Delete an edge
|
|
3057
|
+
* graph.deleteEdgeSrcToDest('X', 'Y');
|
|
3058
|
+
* console.log(graph.hasEdge('X', 'Y')); // false;
|
|
3059
|
+
*
|
|
3060
|
+
* // Edge in other direction should not exist
|
|
3061
|
+
* console.log(graph.hasEdge('Y', 'X')); // false;
|
|
3062
|
+
*
|
|
3063
|
+
* // Other edges should remain
|
|
3064
|
+
* console.log(graph.hasEdge('Y', 'Z')); // true;
|
|
3065
|
+
*
|
|
3066
|
+
* // Delete a vertex
|
|
3067
|
+
* graph.deleteVertex('Y');
|
|
3068
|
+
* console.log(graph.hasVertex('Y')); // false;
|
|
3069
|
+
* console.log(graph.size); // 2;
|
|
3070
|
+
*/
|
|
2531
3071
|
deleteEdge(edgeOrSrcVertexKey, destVertexKey) {
|
|
2532
3072
|
let removed = void 0;
|
|
2533
3073
|
let src, dest;
|
|
@@ -2554,6 +3094,26 @@ var DirectedGraph = class _DirectedGraph extends AbstractGraph {
|
|
|
2554
3094
|
}
|
|
2555
3095
|
return removed;
|
|
2556
3096
|
}
|
|
3097
|
+
/**
|
|
3098
|
+
* Remove a vertex
|
|
3099
|
+
|
|
3100
|
+
|
|
3101
|
+
|
|
3102
|
+
|
|
3103
|
+
|
|
3104
|
+
|
|
3105
|
+
|
|
3106
|
+
|
|
3107
|
+
* @example
|
|
3108
|
+
* // Remove a vertex
|
|
3109
|
+
* const g = new DirectedGraph();
|
|
3110
|
+
* g.addVertex('A');
|
|
3111
|
+
* g.addVertex('B');
|
|
3112
|
+
* g.addEdge('A', 'B');
|
|
3113
|
+
* g.deleteVertex('A');
|
|
3114
|
+
* console.log(g.hasVertex('A')); // false;
|
|
3115
|
+
* console.log(g.hasEdge('A', 'B')); // false;
|
|
3116
|
+
*/
|
|
2557
3117
|
deleteVertex(vertexOrKey) {
|
|
2558
3118
|
let vertexKey;
|
|
2559
3119
|
let vertex;
|
|
@@ -2585,11 +3145,28 @@ var DirectedGraph = class _DirectedGraph extends AbstractGraph {
|
|
|
2585
3145
|
return removed;
|
|
2586
3146
|
}
|
|
2587
3147
|
/**
|
|
2588
|
-
|
|
2589
|
-
|
|
2590
|
-
|
|
2591
|
-
|
|
2592
|
-
|
|
3148
|
+
* Incoming edges of a vertex.
|
|
3149
|
+
* @param vertexOrKey - Vertex or key.
|
|
3150
|
+
* @returns Array of incoming edges.
|
|
3151
|
+
* @remarks Time O(deg_in), Space O(deg_in)
|
|
3152
|
+
|
|
3153
|
+
|
|
3154
|
+
|
|
3155
|
+
|
|
3156
|
+
|
|
3157
|
+
|
|
3158
|
+
|
|
3159
|
+
|
|
3160
|
+
* @example
|
|
3161
|
+
* // Get incoming edges
|
|
3162
|
+
* const g = new DirectedGraph();
|
|
3163
|
+
* g.addVertex('A');
|
|
3164
|
+
* g.addVertex('B');
|
|
3165
|
+
* g.addVertex('C');
|
|
3166
|
+
* g.addEdge('A', 'C');
|
|
3167
|
+
* g.addEdge('B', 'C');
|
|
3168
|
+
* console.log(g.incomingEdgesOf('C').length); // 2;
|
|
3169
|
+
*/
|
|
2593
3170
|
incomingEdgesOf(vertexOrKey) {
|
|
2594
3171
|
const target = this._getVertex(vertexOrKey);
|
|
2595
3172
|
if (target) {
|
|
@@ -2598,11 +3175,28 @@ var DirectedGraph = class _DirectedGraph extends AbstractGraph {
|
|
|
2598
3175
|
return [];
|
|
2599
3176
|
}
|
|
2600
3177
|
/**
|
|
2601
|
-
|
|
2602
|
-
|
|
2603
|
-
|
|
2604
|
-
|
|
2605
|
-
|
|
3178
|
+
* Outgoing edges of a vertex.
|
|
3179
|
+
* @param vertexOrKey - Vertex or key.
|
|
3180
|
+
* @returns Array of outgoing edges.
|
|
3181
|
+
* @remarks Time O(deg_out), Space O(deg_out)
|
|
3182
|
+
|
|
3183
|
+
|
|
3184
|
+
|
|
3185
|
+
|
|
3186
|
+
|
|
3187
|
+
|
|
3188
|
+
|
|
3189
|
+
|
|
3190
|
+
* @example
|
|
3191
|
+
* // Get outgoing edges
|
|
3192
|
+
* const g = new DirectedGraph();
|
|
3193
|
+
* g.addVertex('A');
|
|
3194
|
+
* g.addVertex('B');
|
|
3195
|
+
* g.addVertex('C');
|
|
3196
|
+
* g.addEdge('A', 'B');
|
|
3197
|
+
* g.addEdge('A', 'C');
|
|
3198
|
+
* console.log(g.outgoingEdgesOf('A').length); // 2;
|
|
3199
|
+
*/
|
|
2606
3200
|
outgoingEdgesOf(vertexOrKey) {
|
|
2607
3201
|
const target = this._getVertex(vertexOrKey);
|
|
2608
3202
|
if (target) {
|
|
@@ -2661,11 +3255,44 @@ var DirectedGraph = class _DirectedGraph extends AbstractGraph {
|
|
|
2661
3255
|
return destinations;
|
|
2662
3256
|
}
|
|
2663
3257
|
/**
|
|
2664
|
-
|
|
2665
|
-
|
|
2666
|
-
|
|
2667
|
-
|
|
2668
|
-
|
|
3258
|
+
* Topological sort if DAG; returns `undefined` if a cycle exists.
|
|
3259
|
+
* @param propertyName - `'key'` to map to keys; `'vertex'` to keep instances.
|
|
3260
|
+
* @returns Array of keys/vertices, or `undefined` when cycle is found.
|
|
3261
|
+
* @remarks Time O(V + E), Space O(V)
|
|
3262
|
+
|
|
3263
|
+
|
|
3264
|
+
|
|
3265
|
+
|
|
3266
|
+
|
|
3267
|
+
|
|
3268
|
+
|
|
3269
|
+
|
|
3270
|
+
|
|
3271
|
+
|
|
3272
|
+
|
|
3273
|
+
* @example
|
|
3274
|
+
* // DirectedGraph topologicalSort for task scheduling
|
|
3275
|
+
* const graph = new DirectedGraph<string>();
|
|
3276
|
+
*
|
|
3277
|
+
* // Build a DAG (Directed Acyclic Graph) for task dependencies
|
|
3278
|
+
* graph.addVertex('Design');
|
|
3279
|
+
* graph.addVertex('Implement');
|
|
3280
|
+
* graph.addVertex('Test');
|
|
3281
|
+
* graph.addVertex('Deploy');
|
|
3282
|
+
*
|
|
3283
|
+
* // Add dependency edges
|
|
3284
|
+
* graph.addEdge('Design', 'Implement', 1); // Design must come before Implement
|
|
3285
|
+
* graph.addEdge('Implement', 'Test', 1); // Implement must come before Test
|
|
3286
|
+
* graph.addEdge('Test', 'Deploy', 1); // Test must come before Deploy
|
|
3287
|
+
*
|
|
3288
|
+
* // Topological sort gives valid execution order
|
|
3289
|
+
* const executionOrder = graph.topologicalSort();
|
|
3290
|
+
* console.log(executionOrder); // defined;
|
|
3291
|
+
* console.log(executionOrder); // ['Design', 'Implement', 'Test', 'Deploy'];
|
|
3292
|
+
*
|
|
3293
|
+
* // All vertices should be included
|
|
3294
|
+
* console.log(executionOrder?.length); // 4;
|
|
3295
|
+
*/
|
|
2669
3296
|
topologicalSort(propertyName) {
|
|
2670
3297
|
propertyName = propertyName ?? "key";
|
|
2671
3298
|
const statusMap = /* @__PURE__ */ new Map();
|
|
@@ -2697,6 +3324,24 @@ var DirectedGraph = class _DirectedGraph extends AbstractGraph {
|
|
|
2697
3324
|
if (propertyName === "key") sorted = sorted.map((vertex) => vertex instanceof DirectedVertex ? vertex.key : vertex);
|
|
2698
3325
|
return sorted.reverse();
|
|
2699
3326
|
}
|
|
3327
|
+
/**
|
|
3328
|
+
* Get all edges
|
|
3329
|
+
|
|
3330
|
+
|
|
3331
|
+
|
|
3332
|
+
|
|
3333
|
+
|
|
3334
|
+
|
|
3335
|
+
|
|
3336
|
+
|
|
3337
|
+
* @example
|
|
3338
|
+
* // Get all edges
|
|
3339
|
+
* const g = new DirectedGraph();
|
|
3340
|
+
* g.addVertex('A');
|
|
3341
|
+
* g.addVertex('B');
|
|
3342
|
+
* g.addEdge('A', 'B', 3);
|
|
3343
|
+
* console.log(g.edgeSet().length); // 1;
|
|
3344
|
+
*/
|
|
2700
3345
|
edgeSet() {
|
|
2701
3346
|
let edgeMap = [];
|
|
2702
3347
|
this._outEdgeMap.forEach((outEdges) => {
|
|
@@ -2704,6 +3349,28 @@ var DirectedGraph = class _DirectedGraph extends AbstractGraph {
|
|
|
2704
3349
|
});
|
|
2705
3350
|
return edgeMap;
|
|
2706
3351
|
}
|
|
3352
|
+
/**
|
|
3353
|
+
* Get outgoing neighbors
|
|
3354
|
+
|
|
3355
|
+
|
|
3356
|
+
|
|
3357
|
+
|
|
3358
|
+
|
|
3359
|
+
|
|
3360
|
+
|
|
3361
|
+
|
|
3362
|
+
|
|
3363
|
+
* @example
|
|
3364
|
+
* // Get outgoing neighbors
|
|
3365
|
+
* const g = new DirectedGraph();
|
|
3366
|
+
* g.addVertex('A');
|
|
3367
|
+
* g.addVertex('B');
|
|
3368
|
+
* g.addVertex('C');
|
|
3369
|
+
* g.addEdge('A', 'B');
|
|
3370
|
+
* g.addEdge('A', 'C');
|
|
3371
|
+
* const neighbors = g.getNeighbors('A');
|
|
3372
|
+
* console.log(neighbors.map(v => v.key).sort()); // ['B', 'C'];
|
|
3373
|
+
*/
|
|
2707
3374
|
getNeighbors(vertexOrKey) {
|
|
2708
3375
|
const neighbors = [];
|
|
2709
3376
|
const vertex = this._getVertex(vertexOrKey);
|
|
@@ -2761,10 +3428,31 @@ var DirectedGraph = class _DirectedGraph extends AbstractGraph {
|
|
|
2761
3428
|
return super.clone();
|
|
2762
3429
|
}
|
|
2763
3430
|
/**
|
|
2764
|
-
|
|
2765
|
-
|
|
2766
|
-
|
|
2767
|
-
|
|
3431
|
+
* Tarjan's algorithm for strongly connected components.
|
|
3432
|
+
* @returns `{ dfnMap, lowMap, SCCs }`.
|
|
3433
|
+
* @remarks Time O(V + E), Space O(V + E)
|
|
3434
|
+
|
|
3435
|
+
|
|
3436
|
+
|
|
3437
|
+
|
|
3438
|
+
|
|
3439
|
+
|
|
3440
|
+
|
|
3441
|
+
|
|
3442
|
+
* @example
|
|
3443
|
+
* // Find strongly connected components
|
|
3444
|
+
* const g = new DirectedGraph();
|
|
3445
|
+
* g.addVertex('A');
|
|
3446
|
+
* g.addVertex('B');
|
|
3447
|
+
* g.addVertex('C');
|
|
3448
|
+
* g.addEdge('A', 'B');
|
|
3449
|
+
* g.addEdge('B', 'C');
|
|
3450
|
+
* g.addEdge('C', 'A');
|
|
3451
|
+
* const { SCCs } = g.tarjan();
|
|
3452
|
+
* // A→B→C→A forms one SCC with 3 members
|
|
3453
|
+
* const sccArrays = [...SCCs.values()];
|
|
3454
|
+
* console.log(sccArrays.some(scc => scc.length === 3)); // true;
|
|
3455
|
+
*/
|
|
2768
3456
|
tarjan() {
|
|
2769
3457
|
const dfnMap = /* @__PURE__ */ new Map();
|
|
2770
3458
|
const lowMap = /* @__PURE__ */ new Map();
|
|
@@ -2822,10 +3510,29 @@ var DirectedGraph = class _DirectedGraph extends AbstractGraph {
|
|
|
2822
3510
|
return this.tarjan().lowMap;
|
|
2823
3511
|
}
|
|
2824
3512
|
/**
|
|
2825
|
-
|
|
2826
|
-
|
|
2827
|
-
|
|
2828
|
-
|
|
3513
|
+
* Strongly connected components computed by `tarjan()`.
|
|
3514
|
+
* @returns Map from SCC id to vertices.
|
|
3515
|
+
* @remarks Time O(#SCC + V), Space O(V)
|
|
3516
|
+
|
|
3517
|
+
|
|
3518
|
+
|
|
3519
|
+
|
|
3520
|
+
|
|
3521
|
+
|
|
3522
|
+
|
|
3523
|
+
|
|
3524
|
+
* @example
|
|
3525
|
+
* // Get strongly connected components
|
|
3526
|
+
* const g = new DirectedGraph();
|
|
3527
|
+
* g.addVertex(1);
|
|
3528
|
+
* g.addVertex(2);
|
|
3529
|
+
* g.addVertex(3);
|
|
3530
|
+
* g.addEdge(1, 2);
|
|
3531
|
+
* g.addEdge(2, 3);
|
|
3532
|
+
* g.addEdge(3, 1);
|
|
3533
|
+
* const sccs = g.getSCCs(); // Map<number, VO[]>
|
|
3534
|
+
* console.log(sccs.size); // >= 1;
|
|
3535
|
+
*/
|
|
2829
3536
|
getSCCs() {
|
|
2830
3537
|
return this.tarjan().SCCs;
|
|
2831
3538
|
}
|
|
@@ -2949,12 +3656,27 @@ var UndirectedGraph = class _UndirectedGraph extends AbstractGraph {
|
|
|
2949
3656
|
return new UndirectedEdge(v1, v2, weight ?? this.options.defaultEdgeWeight ?? 1, value);
|
|
2950
3657
|
}
|
|
2951
3658
|
/**
|
|
2952
|
-
|
|
2953
|
-
|
|
2954
|
-
|
|
2955
|
-
|
|
2956
|
-
|
|
2957
|
-
|
|
3659
|
+
* Get an undirected edge between two vertices, if present.
|
|
3660
|
+
* @param v1 - One vertex or key.
|
|
3661
|
+
* @param v2 - The other vertex or key.
|
|
3662
|
+
* @returns Edge instance or `undefined`.
|
|
3663
|
+
* @remarks Time O(1) avg, Space O(1)
|
|
3664
|
+
|
|
3665
|
+
|
|
3666
|
+
|
|
3667
|
+
|
|
3668
|
+
|
|
3669
|
+
|
|
3670
|
+
|
|
3671
|
+
|
|
3672
|
+
* @example
|
|
3673
|
+
* // Get edge between vertices
|
|
3674
|
+
* const g = new UndirectedGraph();
|
|
3675
|
+
* g.addVertex('A');
|
|
3676
|
+
* g.addVertex('B');
|
|
3677
|
+
* g.addEdge('A', 'B', 7);
|
|
3678
|
+
* console.log(g.getEdge('A', 'B')?.weight); // 7;
|
|
3679
|
+
*/
|
|
2958
3680
|
getEdge(v1, v2) {
|
|
2959
3681
|
let edgeMap = [];
|
|
2960
3682
|
if (v1 !== void 0 && v2 !== void 0) {
|
|
@@ -2991,12 +3713,50 @@ var UndirectedGraph = class _UndirectedGraph extends AbstractGraph {
|
|
|
2991
3713
|
return removed;
|
|
2992
3714
|
}
|
|
2993
3715
|
/**
|
|
2994
|
-
|
|
2995
|
-
|
|
2996
|
-
|
|
2997
|
-
|
|
2998
|
-
|
|
2999
|
-
|
|
3716
|
+
* Delete an edge by instance or by a pair of keys.
|
|
3717
|
+
* @param edgeOrOneSideVertexKey - Edge instance or one endpoint vertex/key.
|
|
3718
|
+
* @param otherSideVertexKey - Required second endpoint when deleting by pair.
|
|
3719
|
+
* @returns Removed edge or `undefined`.
|
|
3720
|
+
* @remarks Time O(1) avg, Space O(1)
|
|
3721
|
+
|
|
3722
|
+
|
|
3723
|
+
|
|
3724
|
+
|
|
3725
|
+
|
|
3726
|
+
|
|
3727
|
+
|
|
3728
|
+
|
|
3729
|
+
|
|
3730
|
+
|
|
3731
|
+
|
|
3732
|
+
* @example
|
|
3733
|
+
* // UndirectedGraph deleteEdge and vertex operations
|
|
3734
|
+
* const graph = new UndirectedGraph<string>();
|
|
3735
|
+
*
|
|
3736
|
+
* // Build a simple undirected graph
|
|
3737
|
+
* graph.addVertex('X');
|
|
3738
|
+
* graph.addVertex('Y');
|
|
3739
|
+
* graph.addVertex('Z');
|
|
3740
|
+
* graph.addEdge('X', 'Y', 1);
|
|
3741
|
+
* graph.addEdge('Y', 'Z', 2);
|
|
3742
|
+
* graph.addEdge('X', 'Z', 3);
|
|
3743
|
+
*
|
|
3744
|
+
* // Delete an edge
|
|
3745
|
+
* graph.deleteEdge('X', 'Y');
|
|
3746
|
+
* console.log(graph.hasEdge('X', 'Y')); // false;
|
|
3747
|
+
*
|
|
3748
|
+
* // Bidirectional deletion confirmed
|
|
3749
|
+
* console.log(graph.hasEdge('Y', 'X')); // false;
|
|
3750
|
+
*
|
|
3751
|
+
* // Other edges should remain
|
|
3752
|
+
* console.log(graph.hasEdge('Y', 'Z')); // true;
|
|
3753
|
+
* console.log(graph.hasEdge('Z', 'Y')); // true;
|
|
3754
|
+
*
|
|
3755
|
+
* // Delete a vertex
|
|
3756
|
+
* graph.deleteVertex('Y');
|
|
3757
|
+
* console.log(graph.hasVertex('Y')); // false;
|
|
3758
|
+
* console.log(graph.size); // 2;
|
|
3759
|
+
*/
|
|
3000
3760
|
deleteEdge(edgeOrOneSideVertexKey, otherSideVertexKey) {
|
|
3001
3761
|
let oneSide, otherSide;
|
|
3002
3762
|
if (this.isVertexKey(edgeOrOneSideVertexKey)) {
|
|
@@ -3017,11 +3777,27 @@ var UndirectedGraph = class _UndirectedGraph extends AbstractGraph {
|
|
|
3017
3777
|
}
|
|
3018
3778
|
}
|
|
3019
3779
|
/**
|
|
3020
|
-
|
|
3021
|
-
|
|
3022
|
-
|
|
3023
|
-
|
|
3024
|
-
|
|
3780
|
+
* Delete a vertex and remove it from all neighbor lists.
|
|
3781
|
+
* @param vertexOrKey - Vertex or key.
|
|
3782
|
+
* @returns `true` if removed; otherwise `false`.
|
|
3783
|
+
* @remarks Time O(deg), Space O(1)
|
|
3784
|
+
|
|
3785
|
+
|
|
3786
|
+
|
|
3787
|
+
|
|
3788
|
+
|
|
3789
|
+
|
|
3790
|
+
|
|
3791
|
+
|
|
3792
|
+
* @example
|
|
3793
|
+
* // Remove vertex and edges
|
|
3794
|
+
* const g = new UndirectedGraph();
|
|
3795
|
+
* g.addVertex('A');
|
|
3796
|
+
* g.addVertex('B');
|
|
3797
|
+
* g.addEdge('A', 'B');
|
|
3798
|
+
* g.deleteVertex('A');
|
|
3799
|
+
* console.log(g.hasVertex('A')); // false;
|
|
3800
|
+
*/
|
|
3025
3801
|
deleteVertex(vertexOrKey) {
|
|
3026
3802
|
let vertexKey;
|
|
3027
3803
|
let vertex;
|
|
@@ -3076,10 +3852,25 @@ var UndirectedGraph = class _UndirectedGraph extends AbstractGraph {
|
|
|
3076
3852
|
}
|
|
3077
3853
|
}
|
|
3078
3854
|
/**
|
|
3079
|
-
|
|
3080
|
-
|
|
3081
|
-
|
|
3082
|
-
|
|
3855
|
+
* Unique set of undirected edges across endpoints.
|
|
3856
|
+
* @returns Array of edges.
|
|
3857
|
+
* @remarks Time O(E), Space O(E)
|
|
3858
|
+
|
|
3859
|
+
|
|
3860
|
+
|
|
3861
|
+
|
|
3862
|
+
|
|
3863
|
+
|
|
3864
|
+
|
|
3865
|
+
|
|
3866
|
+
* @example
|
|
3867
|
+
* // Get all edges
|
|
3868
|
+
* const g = new UndirectedGraph();
|
|
3869
|
+
* g.addVertex('A');
|
|
3870
|
+
* g.addVertex('B');
|
|
3871
|
+
* g.addEdge('A', 'B');
|
|
3872
|
+
* console.log(g.edgeSet().length); // 1;
|
|
3873
|
+
*/
|
|
3083
3874
|
edgeSet() {
|
|
3084
3875
|
const edgeSet = /* @__PURE__ */ new Set();
|
|
3085
3876
|
this._edgeMap.forEach((edgeMap) => {
|
|
@@ -3089,6 +3880,52 @@ var UndirectedGraph = class _UndirectedGraph extends AbstractGraph {
|
|
|
3089
3880
|
});
|
|
3090
3881
|
return [...edgeSet];
|
|
3091
3882
|
}
|
|
3883
|
+
/**
|
|
3884
|
+
* UndirectedGraph connectivity and neighbors
|
|
3885
|
+
|
|
3886
|
+
|
|
3887
|
+
|
|
3888
|
+
|
|
3889
|
+
|
|
3890
|
+
|
|
3891
|
+
|
|
3892
|
+
|
|
3893
|
+
|
|
3894
|
+
|
|
3895
|
+
|
|
3896
|
+
* @example
|
|
3897
|
+
* // UndirectedGraph connectivity and neighbors
|
|
3898
|
+
* const graph = new UndirectedGraph<string>();
|
|
3899
|
+
*
|
|
3900
|
+
* // Build a friendship network
|
|
3901
|
+
* const people = ['Alice', 'Bob', 'Charlie', 'Diana', 'Eve'];
|
|
3902
|
+
* for (const person of people) {
|
|
3903
|
+
* graph.addVertex(person);
|
|
3904
|
+
* }
|
|
3905
|
+
*
|
|
3906
|
+
* // Add friendships (undirected edges)
|
|
3907
|
+
* graph.addEdge('Alice', 'Bob', 1);
|
|
3908
|
+
* graph.addEdge('Alice', 'Charlie', 1);
|
|
3909
|
+
* graph.addEdge('Bob', 'Diana', 1);
|
|
3910
|
+
* graph.addEdge('Charlie', 'Eve', 1);
|
|
3911
|
+
* graph.addEdge('Diana', 'Eve', 1);
|
|
3912
|
+
*
|
|
3913
|
+
* // Get friends of each person
|
|
3914
|
+
* const aliceFriends = graph.getNeighbors('Alice');
|
|
3915
|
+
* console.log(aliceFriends[0].key); // 'Bob';
|
|
3916
|
+
* console.log(aliceFriends[1].key); // 'Charlie';
|
|
3917
|
+
* console.log(aliceFriends.length); // 2;
|
|
3918
|
+
*
|
|
3919
|
+
* const dianaFriends = graph.getNeighbors('Diana');
|
|
3920
|
+
* console.log(dianaFriends[0].key); // 'Bob';
|
|
3921
|
+
* console.log(dianaFriends[1].key); // 'Eve';
|
|
3922
|
+
* console.log(dianaFriends.length); // 2;
|
|
3923
|
+
*
|
|
3924
|
+
* // Verify bidirectional friendship
|
|
3925
|
+
* const bobFriends = graph.getNeighbors('Bob');
|
|
3926
|
+
* console.log(bobFriends[0].key); // 'Alice'; // Alice -> Bob -> Alice ✓
|
|
3927
|
+
* console.log(bobFriends[1].key); // 'Diana';
|
|
3928
|
+
*/
|
|
3092
3929
|
getNeighbors(vertexOrKey) {
|
|
3093
3930
|
const neighbors = [];
|
|
3094
3931
|
const vertex = this._getVertex(vertexOrKey);
|
|
@@ -3145,10 +3982,28 @@ var UndirectedGraph = class _UndirectedGraph extends AbstractGraph {
|
|
|
3145
3982
|
return super.clone();
|
|
3146
3983
|
}
|
|
3147
3984
|
/**
|
|
3148
|
-
|
|
3149
|
-
|
|
3150
|
-
|
|
3151
|
-
|
|
3985
|
+
* Tarjan-based bridge and articulation point detection.
|
|
3986
|
+
* @returns `{ dfnMap, lowMap, bridges, cutVertices }`.
|
|
3987
|
+
* @remarks Time O(V + E), Space O(V + E)
|
|
3988
|
+
|
|
3989
|
+
|
|
3990
|
+
|
|
3991
|
+
|
|
3992
|
+
|
|
3993
|
+
|
|
3994
|
+
|
|
3995
|
+
|
|
3996
|
+
* @example
|
|
3997
|
+
* // Find articulation points and bridges
|
|
3998
|
+
* const g = new UndirectedGraph();
|
|
3999
|
+
* g.addVertex('A');
|
|
4000
|
+
* g.addVertex('B');
|
|
4001
|
+
* g.addVertex('C');
|
|
4002
|
+
* g.addEdge('A', 'B');
|
|
4003
|
+
* g.addEdge('B', 'C');
|
|
4004
|
+
* const result = g.tarjan();
|
|
4005
|
+
* console.log(result); // defined;
|
|
4006
|
+
*/
|
|
3152
4007
|
tarjan() {
|
|
3153
4008
|
const dfnMap = /* @__PURE__ */ new Map();
|
|
3154
4009
|
const lowMap = /* @__PURE__ */ new Map();
|
|
@@ -3248,11 +4103,30 @@ var UndirectedGraph = class _UndirectedGraph extends AbstractGraph {
|
|
|
3248
4103
|
return components;
|
|
3249
4104
|
}
|
|
3250
4105
|
/**
|
|
3251
|
-
|
|
3252
|
-
|
|
3253
|
-
|
|
3254
|
-
|
|
3255
|
-
|
|
4106
|
+
* Detect whether the graph contains a cycle.
|
|
4107
|
+
* Uses DFS with parent tracking.
|
|
4108
|
+
* @returns `true` if a cycle exists, `false` otherwise.
|
|
4109
|
+
* @remarks Time O(V + E), Space O(V)
|
|
4110
|
+
|
|
4111
|
+
|
|
4112
|
+
|
|
4113
|
+
|
|
4114
|
+
|
|
4115
|
+
|
|
4116
|
+
|
|
4117
|
+
|
|
4118
|
+
* @example
|
|
4119
|
+
* // Detect cycle
|
|
4120
|
+
* const g = new UndirectedGraph();
|
|
4121
|
+
* g.addVertex('A');
|
|
4122
|
+
* g.addVertex('B');
|
|
4123
|
+
* g.addVertex('C');
|
|
4124
|
+
* g.addEdge('A', 'B');
|
|
4125
|
+
* g.addEdge('B', 'C');
|
|
4126
|
+
* console.log(g.hasCycle()); // false;
|
|
4127
|
+
* g.addEdge('C', 'A');
|
|
4128
|
+
* console.log(g.hasCycle()); // true;
|
|
4129
|
+
*/
|
|
3256
4130
|
hasCycle() {
|
|
3257
4131
|
const visited = /* @__PURE__ */ new Set();
|
|
3258
4132
|
const dfs = /* @__PURE__ */ __name((vertex, parent) => {
|
|
@@ -3274,18 +4148,55 @@ var UndirectedGraph = class _UndirectedGraph extends AbstractGraph {
|
|
|
3274
4148
|
return false;
|
|
3275
4149
|
}
|
|
3276
4150
|
/**
|
|
3277
|
-
|
|
3278
|
-
|
|
3279
|
-
|
|
3280
|
-
|
|
4151
|
+
* Get bridges discovered by `tarjan()`.
|
|
4152
|
+
* @returns Array of edges that are bridges.
|
|
4153
|
+
* @remarks Time O(B), Space O(1)
|
|
4154
|
+
|
|
4155
|
+
|
|
4156
|
+
|
|
4157
|
+
|
|
4158
|
+
|
|
4159
|
+
|
|
4160
|
+
|
|
4161
|
+
|
|
4162
|
+
* @example
|
|
4163
|
+
* // Find bridge edges
|
|
4164
|
+
* const g = new UndirectedGraph();
|
|
4165
|
+
* g.addVertex('A');
|
|
4166
|
+
* g.addVertex('B');
|
|
4167
|
+
* g.addVertex('C');
|
|
4168
|
+
* g.addEdge('A', 'B');
|
|
4169
|
+
* g.addEdge('B', 'C');
|
|
4170
|
+
* const bridges = g.getBridges();
|
|
4171
|
+
* console.log(bridges.length); // 2;
|
|
4172
|
+
*/
|
|
3281
4173
|
getBridges() {
|
|
3282
4174
|
return this.tarjan().bridges;
|
|
3283
4175
|
}
|
|
3284
4176
|
/**
|
|
3285
|
-
|
|
3286
|
-
|
|
3287
|
-
|
|
3288
|
-
|
|
4177
|
+
* Get articulation points discovered by `tarjan()`.
|
|
4178
|
+
* @returns Array of cut vertices.
|
|
4179
|
+
* @remarks Time O(C), Space O(1)
|
|
4180
|
+
|
|
4181
|
+
|
|
4182
|
+
|
|
4183
|
+
|
|
4184
|
+
|
|
4185
|
+
|
|
4186
|
+
|
|
4187
|
+
|
|
4188
|
+
* @example
|
|
4189
|
+
* // Find articulation points
|
|
4190
|
+
* const g = new UndirectedGraph();
|
|
4191
|
+
* g.addVertex('A');
|
|
4192
|
+
* g.addVertex('B');
|
|
4193
|
+
* g.addVertex('C');
|
|
4194
|
+
* g.addEdge('A', 'B');
|
|
4195
|
+
* g.addEdge('B', 'C');
|
|
4196
|
+
* const cuts = g.getCutVertices();
|
|
4197
|
+
* console.log(cuts.length); // 1;
|
|
4198
|
+
* console.log(cuts[0].key); // 'B';
|
|
4199
|
+
*/
|
|
3289
4200
|
getCutVertices() {
|
|
3290
4201
|
return this.tarjan().cutVertices;
|
|
3291
4202
|
}
|