data-structure-typed 1.42.0 → 1.42.2
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/CHANGELOG.md +1 -1
- package/README.md +24 -17
- package/benchmark/report.html +12 -12
- package/benchmark/report.json +104 -104
- package/dist/cjs/src/data-structures/graph/abstract-graph.d.ts +39 -9
- package/dist/cjs/src/data-structures/graph/abstract-graph.js +56 -14
- package/dist/cjs/src/data-structures/graph/abstract-graph.js.map +1 -1
- package/dist/mjs/src/data-structures/graph/abstract-graph.d.ts +39 -9
- package/dist/mjs/src/data-structures/graph/abstract-graph.js +56 -14
- package/dist/umd/data-structure-typed.min.js +1 -1
- package/dist/umd/data-structure-typed.min.js.map +1 -1
- package/package.json +1 -1
- package/src/data-structures/graph/abstract-graph.ts +73 -29
- package/test/unit/data-structures/binary-tree/binary-tree.test.ts +2 -3
- package/test/unit/data-structures/graph/directed-graph.test.ts +35 -1
- package/test/unit/data-structures/graph/undirected-graph.test.ts +34 -0
- package/test/utils/json2html.ts +1 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "data-structure-typed",
|
|
3
|
-
"version": "1.42.
|
|
3
|
+
"version": "1.42.2",
|
|
4
4
|
"description": "Data Structures of Javascript & TypeScript. Binary Tree, BST, Graph, Heap, Priority Queue, Linked List, Queue, Deque, Stack, AVL Tree, Tree Multiset, Trie, Directed Graph, Undirected Graph, Singly Linked List, Doubly Linked List, Max Heap, Max Priority Queue, Min Heap, Min Priority Queue.",
|
|
5
5
|
"main": "dist/cjs/src/index.js",
|
|
6
6
|
"module": "dist/mjs/src/index.js",
|
|
@@ -64,8 +64,7 @@ export abstract class AbstractGraph<
|
|
|
64
64
|
E = any,
|
|
65
65
|
VO extends AbstractVertex<V> = AbstractVertex<V>,
|
|
66
66
|
EO extends AbstractEdge<E> = AbstractEdge<E>
|
|
67
|
-
> implements IGraph<V, E, VO, EO>
|
|
68
|
-
{
|
|
67
|
+
> implements IGraph<V, E, VO, EO> {
|
|
69
68
|
protected _vertices: Map<VertexKey, VO> = new Map<VertexKey, VO>();
|
|
70
69
|
|
|
71
70
|
get vertices(): Map<VertexKey, VO> {
|
|
@@ -236,10 +235,10 @@ export abstract class AbstractGraph<
|
|
|
236
235
|
}
|
|
237
236
|
|
|
238
237
|
const stack: { vertex: VO, path: VO[] }[] = [];
|
|
239
|
-
stack.push({
|
|
238
|
+
stack.push({vertex: vertex1, path: [vertex1]});
|
|
240
239
|
|
|
241
240
|
while (stack.length > 0) {
|
|
242
|
-
const {
|
|
241
|
+
const {vertex, path} = stack.pop()!;
|
|
243
242
|
|
|
244
243
|
if (vertex === vertex2) {
|
|
245
244
|
paths.push(path);
|
|
@@ -250,7 +249,7 @@ export abstract class AbstractGraph<
|
|
|
250
249
|
for (const neighbor of neighbors) {
|
|
251
250
|
if (!path.includes(neighbor)) {
|
|
252
251
|
const newPath = [...path, neighbor];
|
|
253
|
-
stack.push({
|
|
252
|
+
stack.push({vertex: neighbor, path: newPath});
|
|
254
253
|
}
|
|
255
254
|
}
|
|
256
255
|
}
|
|
@@ -258,8 +257,6 @@ export abstract class AbstractGraph<
|
|
|
258
257
|
}
|
|
259
258
|
|
|
260
259
|
|
|
261
|
-
|
|
262
|
-
|
|
263
260
|
/**
|
|
264
261
|
* The function calculates the sum of weights along a given path.
|
|
265
262
|
* @param {VO[]} path - An array of vertices (VO) representing a path in a graph.
|
|
@@ -522,14 +519,14 @@ export abstract class AbstractGraph<
|
|
|
522
519
|
}
|
|
523
520
|
|
|
524
521
|
getMinDist &&
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
}
|
|
522
|
+
distMap.forEach((d, v) => {
|
|
523
|
+
if (v !== srcVertex) {
|
|
524
|
+
if (d < minDist) {
|
|
525
|
+
minDist = d;
|
|
526
|
+
if (genPaths) minDest = v;
|
|
531
527
|
}
|
|
532
|
-
}
|
|
528
|
+
}
|
|
529
|
+
});
|
|
533
530
|
|
|
534
531
|
genPaths && getPaths(minDest);
|
|
535
532
|
|
|
@@ -591,7 +588,7 @@ export abstract class AbstractGraph<
|
|
|
591
588
|
if (vertexOrKey instanceof AbstractVertex) distMap.set(vertexOrKey, Infinity);
|
|
592
589
|
}
|
|
593
590
|
|
|
594
|
-
const heap = new PriorityQueue<{key: number; value: VO}>({comparator: (a, b) => a.key - b.key});
|
|
591
|
+
const heap = new PriorityQueue<{ key: number; value: VO }>({comparator: (a, b) => a.key - b.key});
|
|
595
592
|
heap.add({key: 0, value: srcVertex});
|
|
596
593
|
|
|
597
594
|
distMap.set(srcVertex, 0);
|
|
@@ -802,11 +799,6 @@ export abstract class AbstractGraph<
|
|
|
802
799
|
* Floyd algorithm time: O(VO^3) space: O(VO^2), not support graph with negative weight cycle
|
|
803
800
|
* all pairs
|
|
804
801
|
* The Floyd-Warshall algorithm is used to find the shortest paths between all pairs of nodes in a graph. It employs dynamic programming to compute the shortest paths from any node to any other node. The Floyd-Warshall algorithm's advantage lies in its ability to handle graphs with negative-weight edges, and it can simultaneously compute shortest paths between any two nodes.
|
|
805
|
-
*/
|
|
806
|
-
|
|
807
|
-
/**
|
|
808
|
-
* Floyd algorithm time: O(VO^3) space: O(VO^2), not support graph with negative weight cycle
|
|
809
|
-
* all pairs
|
|
810
802
|
* /
|
|
811
803
|
|
|
812
804
|
/**
|
|
@@ -815,12 +807,12 @@ export abstract class AbstractGraph<
|
|
|
815
807
|
* The Floyd-Warshall algorithm is used to find the shortest paths between all pairs of nodes in a graph. It employs dynamic programming to compute the shortest paths from any node to any other node. The Floyd-Warshall algorithm's advantage lies in its ability to handle graphs with negative-weight edges, and it can simultaneously compute shortest paths between any two nodes.
|
|
816
808
|
* The function implements the Floyd-Warshall algorithm to find the shortest path between all pairs of vertices in a
|
|
817
809
|
* graph.
|
|
818
|
-
* @returns The function `
|
|
810
|
+
* @returns The function `floydWarshall()` returns an object with two properties: `costs` and `predecessor`. The `costs`
|
|
819
811
|
* property is a 2D array of numbers representing the shortest path costs between vertices in a graph. The
|
|
820
812
|
* `predecessor` property is a 2D array of vertices (or `null`) representing the predecessor vertices in the shortest
|
|
821
813
|
* path between vertices in the
|
|
822
814
|
*/
|
|
823
|
-
|
|
815
|
+
floydWarshall(): { costs: number[][]; predecessor: (VO | null)[][] } {
|
|
824
816
|
const idAndVertices = [...this._vertices];
|
|
825
817
|
const n = idAndVertices.length;
|
|
826
818
|
|
|
@@ -871,7 +863,7 @@ export abstract class AbstractGraph<
|
|
|
871
863
|
* Tarjan can find the SSC(strongly connected components), articulation points, and bridges of directed graphs.
|
|
872
864
|
* The `tarjan` function is used to perform various graph analysis tasks such as finding articulation points, bridges,
|
|
873
865
|
* strongly connected components (SCCs), and cycles in a graph.
|
|
874
|
-
* @param {boolean} [
|
|
866
|
+
* @param {boolean} [needCutVertexes] - A boolean value indicating whether or not to calculate and return the
|
|
875
867
|
* articulation points in the graph. Articulation points are the vertices in a graph whose removal would increase the
|
|
876
868
|
* number of connected components in the graph.
|
|
877
869
|
* @param {boolean} [needBridges] - A boolean flag indicating whether the algorithm should find and return the bridges
|
|
@@ -884,13 +876,13 @@ export abstract class AbstractGraph<
|
|
|
884
876
|
* are arrays of vertices that form cycles within the SCCs.
|
|
885
877
|
* @returns The function `tarjan` returns an object with the following properties:
|
|
886
878
|
*/
|
|
887
|
-
tarjan(
|
|
879
|
+
tarjan(needCutVertexes: boolean = false, needBridges: boolean = false, needSCCs: boolean = true, needCycles: boolean = false) {
|
|
888
880
|
// !! in undirected graph we will not let child visit parent when dfs
|
|
889
881
|
// !! articulation point(in dfs search tree not in graph): (cur !== root && cur.has(child)) && (low(child) >= dfn(cur)) || (cur === root && cur.children() >= 2)
|
|
890
882
|
// !! bridge: low(child) > dfn(cur)
|
|
891
883
|
|
|
892
884
|
const defaultConfig = false;
|
|
893
|
-
if (
|
|
885
|
+
if (needCutVertexes === undefined) needCutVertexes = defaultConfig;
|
|
894
886
|
if (needBridges === undefined) needBridges = defaultConfig;
|
|
895
887
|
if (needSCCs === undefined) needSCCs = defaultConfig;
|
|
896
888
|
if (needCycles === undefined) needCycles = defaultConfig;
|
|
@@ -905,7 +897,7 @@ export abstract class AbstractGraph<
|
|
|
905
897
|
|
|
906
898
|
const [root] = vertices.values();
|
|
907
899
|
|
|
908
|
-
const
|
|
900
|
+
const cutVertexes: VO[] = [];
|
|
909
901
|
const bridges: EO[] = [];
|
|
910
902
|
let dfn = 0;
|
|
911
903
|
const dfs = (cur: VO, parent: VO | null) => {
|
|
@@ -929,10 +921,10 @@ export abstract class AbstractGraph<
|
|
|
929
921
|
}
|
|
930
922
|
const curFromMap = dfnMap.get(cur);
|
|
931
923
|
if (childLow !== undefined && curFromMap !== undefined) {
|
|
932
|
-
if (
|
|
924
|
+
if (needCutVertexes) {
|
|
933
925
|
if ((cur === root && childCount >= 2) || (cur !== root && childLow >= curFromMap)) {
|
|
934
926
|
// todo not ensure the logic if (cur === root && childCount >= 2 || ((cur !== root) && (childLow >= curFromMap))) {
|
|
935
|
-
|
|
927
|
+
cutVertexes.push(cur);
|
|
936
928
|
}
|
|
937
929
|
}
|
|
938
930
|
|
|
@@ -983,7 +975,59 @@ export abstract class AbstractGraph<
|
|
|
983
975
|
});
|
|
984
976
|
}
|
|
985
977
|
|
|
986
|
-
return {dfnMap, lowMap, bridges,
|
|
978
|
+
return {dfnMap, lowMap, bridges, cutVertexes, SCCs, cycles};
|
|
979
|
+
}
|
|
980
|
+
|
|
981
|
+
/**
|
|
982
|
+
* The function returns a map that associates each vertex object with its corresponding depth-first
|
|
983
|
+
* number.
|
|
984
|
+
* @returns A Map object with keys of type VO and values of type number.
|
|
985
|
+
*/
|
|
986
|
+
getDFNMap(): Map<VO, number> {
|
|
987
|
+
return this.tarjan(false, false, false, false).dfnMap;
|
|
988
|
+
}
|
|
989
|
+
|
|
990
|
+
/**
|
|
991
|
+
* The function returns a Map object that contains the low values of each vertex in a Tarjan
|
|
992
|
+
* algorithm.
|
|
993
|
+
* @returns The method `getLowMap()` is returning a `Map` object with keys of type `VO` and values of
|
|
994
|
+
* type `number`.
|
|
995
|
+
*/
|
|
996
|
+
getLowMap(): Map<VO, number> {
|
|
997
|
+
return this.tarjan(false, false, false, false).lowMap;
|
|
998
|
+
}
|
|
999
|
+
|
|
1000
|
+
/**
|
|
1001
|
+
* The function `getCycles` returns a map of cycles found using the Tarjan algorithm.
|
|
1002
|
+
* @returns The function `getCycles()` is returning a `Map<number, VO[]>`.
|
|
1003
|
+
*/
|
|
1004
|
+
getCycles(): Map<number, VO[]> {
|
|
1005
|
+
return this.tarjan(false, false, false, true).cycles;
|
|
1006
|
+
}
|
|
1007
|
+
|
|
1008
|
+
/**
|
|
1009
|
+
* The function "getCutVertexes" returns an array of cut vertexes using the Tarjan algorithm.
|
|
1010
|
+
* @returns an array of VO objects, specifically the cut vertexes.
|
|
1011
|
+
*/
|
|
1012
|
+
getCutVertexes(): VO[] {
|
|
1013
|
+
return this.tarjan(true, false, false, false).cutVertexes;
|
|
1014
|
+
}
|
|
1015
|
+
|
|
1016
|
+
/**
|
|
1017
|
+
* The function "getSCCs" returns a map of strongly connected components (SCCs) using the Tarjan
|
|
1018
|
+
* algorithm.
|
|
1019
|
+
* @returns a map where the keys are numbers and the values are arrays of VO objects.
|
|
1020
|
+
*/
|
|
1021
|
+
getSCCs(): Map<number, VO[]> {
|
|
1022
|
+
return this.tarjan(false, false, true, false).SCCs;
|
|
1023
|
+
}
|
|
1024
|
+
|
|
1025
|
+
/**
|
|
1026
|
+
* The function "getBridges" returns an array of bridges using the Tarjan algorithm.
|
|
1027
|
+
* @returns the bridges found using the Tarjan algorithm.
|
|
1028
|
+
*/
|
|
1029
|
+
getBridges() {
|
|
1030
|
+
return this.tarjan(false, true, false, false).bridges;
|
|
987
1031
|
}
|
|
988
1032
|
|
|
989
1033
|
protected abstract _addEdgeOnly(edge: EO): boolean;
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import {AVLTree, AVLTreeNode, BinaryTree, BinaryTreeNode, IterationType} from '../../../../src';
|
|
2
|
-
import {isDebugTest} from '../../../config';
|
|
2
|
+
// import {isDebugTest} from '../../../config';
|
|
3
3
|
|
|
4
|
-
const isDebug = isDebugTest;
|
|
5
|
-
// const isDebug = true;
|
|
4
|
+
// const isDebug = isDebugTest;
|
|
6
5
|
|
|
7
6
|
describe('BinaryTreeNode', () => {
|
|
8
7
|
it('should create an instance of BinaryTreeNode', () => {
|
|
@@ -340,7 +340,7 @@ describe('Inherit from DirectedGraph and perform operations test2.', () => {
|
|
|
340
340
|
expect(min).toBe(Infinity);
|
|
341
341
|
expect(minPath).toBeInstanceOf(Array);
|
|
342
342
|
|
|
343
|
-
const floydResult = myGraph.
|
|
343
|
+
const floydResult = myGraph.floydWarshall();
|
|
344
344
|
expect(floydResult).toBeTruthy();
|
|
345
345
|
if (floydResult) {
|
|
346
346
|
const {costs, predecessor} = floydResult;
|
|
@@ -562,3 +562,37 @@ describe('Inherit from DirectedGraph and perform operations test2.', () => {
|
|
|
562
562
|
}
|
|
563
563
|
});
|
|
564
564
|
});
|
|
565
|
+
|
|
566
|
+
|
|
567
|
+
describe('cycles, strongly connected components, bridges, articular points in DirectedGraph', () => {
|
|
568
|
+
const graph = new DirectedGraph();
|
|
569
|
+
graph.addVertex('A');
|
|
570
|
+
graph.addVertex('B');
|
|
571
|
+
graph.addVertex('C');
|
|
572
|
+
graph.addVertex('D');
|
|
573
|
+
graph.addVertex('E');
|
|
574
|
+
graph.addVertex('F');
|
|
575
|
+
graph.addVertex('G');
|
|
576
|
+
graph.addVertex('H');
|
|
577
|
+
graph.addEdge('A', 'B');
|
|
578
|
+
graph.addEdge('B', 'D');
|
|
579
|
+
graph.addEdge('D', 'C');
|
|
580
|
+
graph.addEdge('C', 'A');
|
|
581
|
+
graph.addEdge('C', 'B');
|
|
582
|
+
graph.addEdge('D', 'E');
|
|
583
|
+
graph.addEdge('E', 'G');
|
|
584
|
+
graph.addEdge('E', 'H');
|
|
585
|
+
graph.addEdge('H', 'F');
|
|
586
|
+
const cycles = graph.getCycles();
|
|
587
|
+
const scCs = graph.getSCCs();
|
|
588
|
+
const bridges = graph.getBridges();
|
|
589
|
+
const cutVertexes = graph.getCutVertexes();
|
|
590
|
+
const dfnMap = graph.getDFNMap();
|
|
591
|
+
const lowMap = graph.getLowMap();
|
|
592
|
+
expect(cycles.size).toBe(1)
|
|
593
|
+
expect(scCs.size).toBe(5)
|
|
594
|
+
expect(bridges.length).toBe(4)
|
|
595
|
+
expect(cutVertexes.length).toBe(4)
|
|
596
|
+
expect(dfnMap.size).toBe(8)
|
|
597
|
+
expect(lowMap.size).toBe(8)
|
|
598
|
+
});
|
|
@@ -174,3 +174,37 @@ describe('UndirectedGraph', () => {
|
|
|
174
174
|
expect(minWeightedPath?.minPath?.[4]?.key).toBe('Intersection_5')
|
|
175
175
|
});
|
|
176
176
|
});
|
|
177
|
+
|
|
178
|
+
|
|
179
|
+
describe('cycles, strongly connected components, bridges, articular points in UndirectedGraph', () => {
|
|
180
|
+
const graph = new UndirectedGraph();
|
|
181
|
+
graph.addVertex('A');
|
|
182
|
+
graph.addVertex('B');
|
|
183
|
+
graph.addVertex('C');
|
|
184
|
+
graph.addVertex('D');
|
|
185
|
+
graph.addVertex('E');
|
|
186
|
+
graph.addVertex('F');
|
|
187
|
+
graph.addVertex('G');
|
|
188
|
+
graph.addVertex('H');
|
|
189
|
+
graph.addEdge('A', 'B');
|
|
190
|
+
graph.addEdge('B', 'D');
|
|
191
|
+
graph.addEdge('D', 'C');
|
|
192
|
+
graph.addEdge('C', 'A');
|
|
193
|
+
graph.addEdge('C', 'B');
|
|
194
|
+
graph.addEdge('D', 'E');
|
|
195
|
+
graph.addEdge('E', 'G');
|
|
196
|
+
graph.addEdge('E', 'H');
|
|
197
|
+
graph.addEdge('H', 'F');
|
|
198
|
+
const cycles = graph.getCycles();
|
|
199
|
+
const scCs = graph.getSCCs();
|
|
200
|
+
const bridges = graph.getBridges();
|
|
201
|
+
const cutVertexes = graph.getCutVertexes();
|
|
202
|
+
const dfnMap = graph.getDFNMap();
|
|
203
|
+
const lowMap = graph.getLowMap();
|
|
204
|
+
expect(cycles.size).toBe(1)
|
|
205
|
+
expect(scCs.size).toBe(5)
|
|
206
|
+
expect(bridges.length).toBe(4)
|
|
207
|
+
expect(cutVertexes.length).toBe(4)
|
|
208
|
+
expect(dfnMap.size).toBe(8)
|
|
209
|
+
expect(lowMap.size).toBe(8)
|
|
210
|
+
});
|
package/test/utils/json2html.ts
CHANGED
|
@@ -109,7 +109,7 @@ function drawTable(arr: any[]): string {
|
|
|
109
109
|
const content = arr.map(rowObj => drawRow(cols, rowObj));
|
|
110
110
|
const headingHtml = '<tr><th>' + cols.join('</th><th>') + '</th></tr>';
|
|
111
111
|
const contentHtml = '<tr>' + content.join('</tr><tr>') + '</tr>';
|
|
112
|
-
return '<table>' + headingHtml + contentHtml + '</table>';
|
|
112
|
+
return '<table style="display: table; width:100%; table-layout: fixed;">' + headingHtml + contentHtml + '</table>';
|
|
113
113
|
}
|
|
114
114
|
|
|
115
115
|
function _render(name: string, data: any, options: Json2htmlOptions, level: number, altRow: number): string {
|