data-structure-typed 1.42.1 → 1.42.3
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 +12 -12
- package/benchmark/report.html +12 -12
- package/benchmark/report.json +105 -105
- package/dist/cjs/src/data-structures/binary-tree/binary-tree.d.ts +1 -1
- package/dist/cjs/src/data-structures/binary-tree/binary-tree.js +1 -1
- package/dist/cjs/src/data-structures/binary-tree/binary-tree.js.map +1 -1
- 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/binary-tree/binary-tree.d.ts +1 -1
- package/dist/mjs/src/data-structures/binary-tree/binary-tree.js +2 -2
- 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 +2 -2
- package/src/data-structures/binary-tree/binary-tree.ts +30 -31
- package/src/data-structures/graph/abstract-graph.ts +70 -22
- package/test/performance/reportor.ts +1 -0
- package/test/unit/data-structures/binary-tree/binary-tree.test.ts +34 -15
- package/test/unit/data-structures/binary-tree/bst.test.ts +13 -0
- package/test/unit/data-structures/graph/directed-graph.test.ts +34 -1
- package/test/unit/data-structures/graph/salty-edges.json +875 -1
- package/test/unit/data-structures/graph/salty-vertexes.json +200 -1
- package/test/unit/data-structures/graph/undirected-graph.test.ts +41 -8
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "data-structure-typed",
|
|
3
|
-
"version": "1.42.
|
|
3
|
+
"version": "1.42.3",
|
|
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",
|
|
@@ -41,7 +41,7 @@
|
|
|
41
41
|
"copy:to-subs": "sh scripts/copy_to_all_subs.sh",
|
|
42
42
|
"publish:subs": "npm run copy:to-subs && sh scripts/publish_all_subs.sh",
|
|
43
43
|
"publish:docs": "sh scripts/publish_docs.sh",
|
|
44
|
-
"publish:all": "npm run ci && npm
|
|
44
|
+
"publish:all": "npm run ci && npm publish && npm run publish:docs && npm run publish:subs"
|
|
45
45
|
},
|
|
46
46
|
"repository": {
|
|
47
47
|
"type": "git",
|
|
@@ -108,7 +108,8 @@ export class BinaryTreeNode<V = any, N extends BinaryTreeNode<V, N> = BinaryTree
|
|
|
108
108
|
* @template N - The type of the binary tree's nodes.
|
|
109
109
|
*/
|
|
110
110
|
export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode<V, BinaryTreeNodeNested<V>>>
|
|
111
|
-
implements IBinaryTree<V, N>
|
|
111
|
+
implements IBinaryTree<V, N>
|
|
112
|
+
{
|
|
112
113
|
iterationType: IterationType = IterationType.ITERATIVE;
|
|
113
114
|
|
|
114
115
|
/**
|
|
@@ -140,8 +141,6 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
140
141
|
return this._size;
|
|
141
142
|
}
|
|
142
143
|
|
|
143
|
-
protected defaultOneParamCallback = (node: N) => node.key;
|
|
144
|
-
|
|
145
144
|
/**
|
|
146
145
|
* Creates a new instance of BinaryTreeNode with the given key and value.
|
|
147
146
|
* @param {BTNKey} key - The key for the new node.
|
|
@@ -390,7 +389,7 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
390
389
|
return -1;
|
|
391
390
|
}
|
|
392
391
|
|
|
393
|
-
const stack: {
|
|
392
|
+
const stack: {node: N; depth: number}[] = [{node: beginRoot, depth: 0}];
|
|
394
393
|
let maxHeight = 0;
|
|
395
394
|
|
|
396
395
|
while (stack.length > 0) {
|
|
@@ -850,21 +849,21 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
850
849
|
beginRoot?: BTNKey | N | null,
|
|
851
850
|
iterationType?: IterationType,
|
|
852
851
|
includeNull?: false
|
|
853
|
-
): ReturnType<C>[]
|
|
852
|
+
): ReturnType<C>[];
|
|
854
853
|
|
|
855
854
|
subTreeTraverse<C extends BTNCallback<N>>(
|
|
856
855
|
callback?: C,
|
|
857
856
|
beginRoot?: BTNKey | N | null,
|
|
858
857
|
iterationType?: IterationType,
|
|
859
858
|
includeNull?: undefined
|
|
860
|
-
): ReturnType<C>[]
|
|
859
|
+
): ReturnType<C>[];
|
|
861
860
|
|
|
862
861
|
subTreeTraverse<C extends BTNCallback<N | null>>(
|
|
863
862
|
callback?: C,
|
|
864
863
|
beginRoot?: BTNKey | N | null,
|
|
865
864
|
iterationType?: IterationType,
|
|
866
865
|
includeNull?: true
|
|
867
|
-
): ReturnType<C>[]
|
|
866
|
+
): ReturnType<C>[];
|
|
868
867
|
|
|
869
868
|
/**
|
|
870
869
|
* The function `subTreeTraverse` traverses a binary tree and applies a callback function to each
|
|
@@ -908,7 +907,7 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
908
907
|
|
|
909
908
|
_traverse(beginRoot);
|
|
910
909
|
} else {
|
|
911
|
-
const stack: (N| null)[] = [beginRoot];
|
|
910
|
+
const stack: (N | null)[] = [beginRoot];
|
|
912
911
|
|
|
913
912
|
while (stack.length > 0) {
|
|
914
913
|
const cur = stack.pop();
|
|
@@ -933,7 +932,7 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
933
932
|
beginRoot?: N | null,
|
|
934
933
|
iterationType?: IterationType,
|
|
935
934
|
includeNull?: false
|
|
936
|
-
): ReturnType<C>[]
|
|
935
|
+
): ReturnType<C>[];
|
|
937
936
|
|
|
938
937
|
dfs<C extends BTNCallback<N>>(
|
|
939
938
|
callback?: C,
|
|
@@ -941,7 +940,7 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
941
940
|
beginRoot?: N | null,
|
|
942
941
|
iterationType?: IterationType,
|
|
943
942
|
includeNull?: undefined
|
|
944
|
-
): ReturnType<C>[]
|
|
943
|
+
): ReturnType<C>[];
|
|
945
944
|
|
|
946
945
|
dfs<C extends BTNCallback<N | null>>(
|
|
947
946
|
callback?: C,
|
|
@@ -949,7 +948,7 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
949
948
|
beginRoot?: N | null,
|
|
950
949
|
iterationType?: IterationType,
|
|
951
950
|
includeNull?: true
|
|
952
|
-
): ReturnType<C>[]
|
|
951
|
+
): ReturnType<C>[];
|
|
953
952
|
|
|
954
953
|
/**
|
|
955
954
|
* The `dfs` function performs a depth-first search traversal on a binary tree, executing a callback
|
|
@@ -1019,7 +1018,7 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
1019
1018
|
_traverse(beginRoot);
|
|
1020
1019
|
} else {
|
|
1021
1020
|
// 0: visit, 1: print
|
|
1022
|
-
const stack: {
|
|
1021
|
+
const stack: {opt: 0 | 1; node: N | null | undefined}[] = [{opt: 0, node: beginRoot}];
|
|
1023
1022
|
|
|
1024
1023
|
while (stack.length > 0) {
|
|
1025
1024
|
const cur = stack.pop();
|
|
@@ -1066,21 +1065,21 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
1066
1065
|
beginRoot?: N | null,
|
|
1067
1066
|
iterationType?: IterationType,
|
|
1068
1067
|
includeNull?: false
|
|
1069
|
-
): ReturnType<C>[]
|
|
1068
|
+
): ReturnType<C>[];
|
|
1070
1069
|
|
|
1071
1070
|
bfs<C extends BTNCallback<N>>(
|
|
1072
1071
|
callback?: C,
|
|
1073
1072
|
beginRoot?: N | null,
|
|
1074
1073
|
iterationType?: IterationType,
|
|
1075
1074
|
includeNull?: undefined
|
|
1076
|
-
): ReturnType<C>[]
|
|
1075
|
+
): ReturnType<C>[];
|
|
1077
1076
|
|
|
1078
1077
|
bfs<C extends BTNCallback<N | null>>(
|
|
1079
1078
|
callback?: C,
|
|
1080
1079
|
beginRoot?: N | null,
|
|
1081
1080
|
iterationType?: IterationType,
|
|
1082
1081
|
includeNull?: true
|
|
1083
|
-
): ReturnType<C>[]
|
|
1082
|
+
): ReturnType<C>[];
|
|
1084
1083
|
|
|
1085
1084
|
/**
|
|
1086
1085
|
* The bfs function performs a breadth-first search traversal on a binary tree, executing a callback
|
|
@@ -1123,7 +1122,6 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
1123
1122
|
if (current.right) queue.push(current.right);
|
|
1124
1123
|
}
|
|
1125
1124
|
|
|
1126
|
-
|
|
1127
1125
|
traverse(level + 1);
|
|
1128
1126
|
};
|
|
1129
1127
|
|
|
@@ -1144,7 +1142,6 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
1144
1142
|
if (current.left) queue.push(current.left);
|
|
1145
1143
|
if (current.right) queue.push(current.right);
|
|
1146
1144
|
}
|
|
1147
|
-
|
|
1148
1145
|
}
|
|
1149
1146
|
}
|
|
1150
1147
|
}
|
|
@@ -1152,25 +1149,25 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
1152
1149
|
}
|
|
1153
1150
|
|
|
1154
1151
|
listLevels<C extends BTNCallback<N>>(
|
|
1155
|
-
callback?: C
|
|
1156
|
-
beginRoot?: N | null
|
|
1152
|
+
callback?: C,
|
|
1153
|
+
beginRoot?: N | null,
|
|
1157
1154
|
iterationType?: IterationType,
|
|
1158
1155
|
includeNull?: false
|
|
1159
|
-
): ReturnType<C>[][]
|
|
1156
|
+
): ReturnType<C>[][];
|
|
1160
1157
|
|
|
1161
1158
|
listLevels<C extends BTNCallback<N>>(
|
|
1162
|
-
callback?: C
|
|
1163
|
-
beginRoot?: N | null
|
|
1159
|
+
callback?: C,
|
|
1160
|
+
beginRoot?: N | null,
|
|
1164
1161
|
iterationType?: IterationType,
|
|
1165
1162
|
includeNull?: undefined
|
|
1166
|
-
): ReturnType<C>[][]
|
|
1163
|
+
): ReturnType<C>[][];
|
|
1167
1164
|
|
|
1168
1165
|
listLevels<C extends BTNCallback<N | null>>(
|
|
1169
|
-
callback?: C
|
|
1170
|
-
beginRoot?: N | null
|
|
1166
|
+
callback?: C,
|
|
1167
|
+
beginRoot?: N | null,
|
|
1171
1168
|
iterationType?: IterationType,
|
|
1172
1169
|
includeNull?: true
|
|
1173
|
-
): ReturnType<C>[][]
|
|
1170
|
+
): ReturnType<C>[][];
|
|
1174
1171
|
|
|
1175
1172
|
/**
|
|
1176
1173
|
* The `listLevels` function takes a binary tree node and a callback function, and returns an array
|
|
@@ -1204,7 +1201,7 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
1204
1201
|
if (includeNull) {
|
|
1205
1202
|
if (node && node.left !== undefined) _recursive(node.left, level + 1);
|
|
1206
1203
|
if (node && node.right !== undefined) _recursive(node.right, level + 1);
|
|
1207
|
-
} else
|
|
1204
|
+
} else {
|
|
1208
1205
|
if (node && node.left) _recursive(node.left, level + 1);
|
|
1209
1206
|
if (node && node.right) _recursive(node.right, level + 1);
|
|
1210
1207
|
}
|
|
@@ -1224,7 +1221,7 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
1224
1221
|
if (includeNull) {
|
|
1225
1222
|
if (node && node.right !== undefined) stack.push([node.right, level + 1]);
|
|
1226
1223
|
if (node && node.left !== undefined) stack.push([node.left, level + 1]);
|
|
1227
|
-
} else
|
|
1224
|
+
} else {
|
|
1228
1225
|
if (node && node.right) stack.push([node.right, level + 1]);
|
|
1229
1226
|
if (node && node.left) stack.push([node.left, level + 1]);
|
|
1230
1227
|
}
|
|
@@ -1273,8 +1270,6 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
1273
1270
|
return y;
|
|
1274
1271
|
}
|
|
1275
1272
|
|
|
1276
|
-
// --- start additional methods ---
|
|
1277
|
-
|
|
1278
1273
|
/**
|
|
1279
1274
|
* The `morris` function performs a depth-first traversal of a binary tree using the Morris traversal
|
|
1280
1275
|
* algorithm and returns an array of values obtained by applying a callback function to each node.
|
|
@@ -1374,6 +1369,8 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
1374
1369
|
return ans;
|
|
1375
1370
|
}
|
|
1376
1371
|
|
|
1372
|
+
// --- start additional methods ---
|
|
1373
|
+
|
|
1377
1374
|
/**
|
|
1378
1375
|
* The above function is an iterator for a binary tree that can be used to traverse the tree in
|
|
1379
1376
|
* either an iterative or recursive manner.
|
|
@@ -1383,7 +1380,7 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
1383
1380
|
* @returns The `*[Symbol.iterator]` method returns a generator object that yields the keys of the
|
|
1384
1381
|
* binary tree nodes in a specific order.
|
|
1385
1382
|
*/
|
|
1386
|
-
*
|
|
1383
|
+
*[Symbol.iterator](node = this.root): Generator<BTNKey, void, undefined> {
|
|
1387
1384
|
if (!node) {
|
|
1388
1385
|
return;
|
|
1389
1386
|
}
|
|
@@ -1416,6 +1413,8 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
1416
1413
|
}
|
|
1417
1414
|
}
|
|
1418
1415
|
|
|
1416
|
+
protected defaultOneParamCallback = (node: N) => node.key;
|
|
1417
|
+
|
|
1419
1418
|
/**
|
|
1420
1419
|
* Swap the data of two nodes in the binary tree.
|
|
1421
1420
|
* @param {N} srcNode - The source node to swap.
|
|
@@ -235,11 +235,11 @@ export abstract class AbstractGraph<
|
|
|
235
235
|
return [];
|
|
236
236
|
}
|
|
237
237
|
|
|
238
|
-
const stack: {
|
|
239
|
-
stack.push({
|
|
238
|
+
const stack: {vertex: VO; path: VO[]}[] = [];
|
|
239
|
+
stack.push({vertex: vertex1, path: [vertex1]});
|
|
240
240
|
|
|
241
241
|
while (stack.length > 0) {
|
|
242
|
-
const {
|
|
242
|
+
const {vertex, path} = stack.pop()!;
|
|
243
243
|
|
|
244
244
|
if (vertex === vertex2) {
|
|
245
245
|
paths.push(path);
|
|
@@ -250,16 +250,13 @@ export abstract class AbstractGraph<
|
|
|
250
250
|
for (const neighbor of neighbors) {
|
|
251
251
|
if (!path.includes(neighbor)) {
|
|
252
252
|
const newPath = [...path, neighbor];
|
|
253
|
-
stack.push({
|
|
253
|
+
stack.push({vertex: neighbor, path: newPath});
|
|
254
254
|
}
|
|
255
255
|
}
|
|
256
256
|
}
|
|
257
257
|
return paths;
|
|
258
258
|
}
|
|
259
259
|
|
|
260
|
-
|
|
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.
|
|
@@ -369,7 +366,6 @@ export abstract class AbstractGraph<
|
|
|
369
366
|
} else {
|
|
370
367
|
return this.dijkstra(v1, v2, true, true)?.minPath ?? [];
|
|
371
368
|
}
|
|
372
|
-
|
|
373
369
|
} else {
|
|
374
370
|
// DFS
|
|
375
371
|
let minPath: VO[] = [];
|
|
@@ -802,11 +798,6 @@ export abstract class AbstractGraph<
|
|
|
802
798
|
* Floyd algorithm time: O(VO^3) space: O(VO^2), not support graph with negative weight cycle
|
|
803
799
|
* all pairs
|
|
804
800
|
* 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
801
|
* /
|
|
811
802
|
|
|
812
803
|
/**
|
|
@@ -815,12 +806,12 @@ export abstract class AbstractGraph<
|
|
|
815
806
|
* 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
807
|
* The function implements the Floyd-Warshall algorithm to find the shortest path between all pairs of vertices in a
|
|
817
808
|
* graph.
|
|
818
|
-
* @returns The function `
|
|
809
|
+
* @returns The function `floydWarshall()` returns an object with two properties: `costs` and `predecessor`. The `costs`
|
|
819
810
|
* property is a 2D array of numbers representing the shortest path costs between vertices in a graph. The
|
|
820
811
|
* `predecessor` property is a 2D array of vertices (or `null`) representing the predecessor vertices in the shortest
|
|
821
812
|
* path between vertices in the
|
|
822
813
|
*/
|
|
823
|
-
|
|
814
|
+
floydWarshall(): {costs: number[][]; predecessor: (VO | null)[][]} {
|
|
824
815
|
const idAndVertices = [...this._vertices];
|
|
825
816
|
const n = idAndVertices.length;
|
|
826
817
|
|
|
@@ -871,7 +862,7 @@ export abstract class AbstractGraph<
|
|
|
871
862
|
* Tarjan can find the SSC(strongly connected components), articulation points, and bridges of directed graphs.
|
|
872
863
|
* The `tarjan` function is used to perform various graph analysis tasks such as finding articulation points, bridges,
|
|
873
864
|
* strongly connected components (SCCs), and cycles in a graph.
|
|
874
|
-
* @param {boolean} [
|
|
865
|
+
* @param {boolean} [needCutVertexes] - A boolean value indicating whether or not to calculate and return the
|
|
875
866
|
* articulation points in the graph. Articulation points are the vertices in a graph whose removal would increase the
|
|
876
867
|
* number of connected components in the graph.
|
|
877
868
|
* @param {boolean} [needBridges] - A boolean flag indicating whether the algorithm should find and return the bridges
|
|
@@ -884,13 +875,18 @@ export abstract class AbstractGraph<
|
|
|
884
875
|
* are arrays of vertices that form cycles within the SCCs.
|
|
885
876
|
* @returns The function `tarjan` returns an object with the following properties:
|
|
886
877
|
*/
|
|
887
|
-
tarjan(
|
|
878
|
+
tarjan(
|
|
879
|
+
needCutVertexes: boolean = false,
|
|
880
|
+
needBridges: boolean = false,
|
|
881
|
+
needSCCs: boolean = true,
|
|
882
|
+
needCycles: boolean = false
|
|
883
|
+
) {
|
|
888
884
|
// !! in undirected graph we will not let child visit parent when dfs
|
|
889
885
|
// !! articulation point(in dfs search tree not in graph): (cur !== root && cur.has(child)) && (low(child) >= dfn(cur)) || (cur === root && cur.children() >= 2)
|
|
890
886
|
// !! bridge: low(child) > dfn(cur)
|
|
891
887
|
|
|
892
888
|
const defaultConfig = false;
|
|
893
|
-
if (
|
|
889
|
+
if (needCutVertexes === undefined) needCutVertexes = defaultConfig;
|
|
894
890
|
if (needBridges === undefined) needBridges = defaultConfig;
|
|
895
891
|
if (needSCCs === undefined) needSCCs = defaultConfig;
|
|
896
892
|
if (needCycles === undefined) needCycles = defaultConfig;
|
|
@@ -905,7 +901,7 @@ export abstract class AbstractGraph<
|
|
|
905
901
|
|
|
906
902
|
const [root] = vertices.values();
|
|
907
903
|
|
|
908
|
-
const
|
|
904
|
+
const cutVertexes: VO[] = [];
|
|
909
905
|
const bridges: EO[] = [];
|
|
910
906
|
let dfn = 0;
|
|
911
907
|
const dfs = (cur: VO, parent: VO | null) => {
|
|
@@ -929,10 +925,10 @@ export abstract class AbstractGraph<
|
|
|
929
925
|
}
|
|
930
926
|
const curFromMap = dfnMap.get(cur);
|
|
931
927
|
if (childLow !== undefined && curFromMap !== undefined) {
|
|
932
|
-
if (
|
|
928
|
+
if (needCutVertexes) {
|
|
933
929
|
if ((cur === root && childCount >= 2) || (cur !== root && childLow >= curFromMap)) {
|
|
934
930
|
// todo not ensure the logic if (cur === root && childCount >= 2 || ((cur !== root) && (childLow >= curFromMap))) {
|
|
935
|
-
|
|
931
|
+
cutVertexes.push(cur);
|
|
936
932
|
}
|
|
937
933
|
}
|
|
938
934
|
|
|
@@ -983,7 +979,59 @@ export abstract class AbstractGraph<
|
|
|
983
979
|
});
|
|
984
980
|
}
|
|
985
981
|
|
|
986
|
-
return {dfnMap, lowMap, bridges,
|
|
982
|
+
return {dfnMap, lowMap, bridges, cutVertexes, SCCs, cycles};
|
|
983
|
+
}
|
|
984
|
+
|
|
985
|
+
/**
|
|
986
|
+
* The function returns a map that associates each vertex object with its corresponding depth-first
|
|
987
|
+
* number.
|
|
988
|
+
* @returns A Map object with keys of type VO and values of type number.
|
|
989
|
+
*/
|
|
990
|
+
getDFNMap(): Map<VO, number> {
|
|
991
|
+
return this.tarjan(false, false, false, false).dfnMap;
|
|
992
|
+
}
|
|
993
|
+
|
|
994
|
+
/**
|
|
995
|
+
* The function returns a Map object that contains the low values of each vertex in a Tarjan
|
|
996
|
+
* algorithm.
|
|
997
|
+
* @returns The method `getLowMap()` is returning a `Map` object with keys of type `VO` and values of
|
|
998
|
+
* type `number`.
|
|
999
|
+
*/
|
|
1000
|
+
getLowMap(): Map<VO, number> {
|
|
1001
|
+
return this.tarjan(false, false, false, false).lowMap;
|
|
1002
|
+
}
|
|
1003
|
+
|
|
1004
|
+
/**
|
|
1005
|
+
* The function `getCycles` returns a map of cycles found using the Tarjan algorithm.
|
|
1006
|
+
* @returns The function `getCycles()` is returning a `Map<number, VO[]>`.
|
|
1007
|
+
*/
|
|
1008
|
+
getCycles(): Map<number, VO[]> {
|
|
1009
|
+
return this.tarjan(false, false, false, true).cycles;
|
|
1010
|
+
}
|
|
1011
|
+
|
|
1012
|
+
/**
|
|
1013
|
+
* The function "getCutVertexes" returns an array of cut vertexes using the Tarjan algorithm.
|
|
1014
|
+
* @returns an array of VO objects, specifically the cut vertexes.
|
|
1015
|
+
*/
|
|
1016
|
+
getCutVertexes(): VO[] {
|
|
1017
|
+
return this.tarjan(true, false, false, false).cutVertexes;
|
|
1018
|
+
}
|
|
1019
|
+
|
|
1020
|
+
/**
|
|
1021
|
+
* The function "getSCCs" returns a map of strongly connected components (SCCs) using the Tarjan
|
|
1022
|
+
* algorithm.
|
|
1023
|
+
* @returns a map where the keys are numbers and the values are arrays of VO objects.
|
|
1024
|
+
*/
|
|
1025
|
+
getSCCs(): Map<number, VO[]> {
|
|
1026
|
+
return this.tarjan(false, false, true, false).SCCs;
|
|
1027
|
+
}
|
|
1028
|
+
|
|
1029
|
+
/**
|
|
1030
|
+
* The function "getBridges" returns an array of bridges using the Tarjan algorithm.
|
|
1031
|
+
* @returns the bridges found using the Tarjan algorithm.
|
|
1032
|
+
*/
|
|
1033
|
+
getBridges() {
|
|
1034
|
+
return this.tarjan(false, true, false, false).bridges;
|
|
987
1035
|
}
|
|
988
1036
|
|
|
989
1037
|
protected abstract _addEdgeOnly(edge: EO): boolean;
|
|
@@ -107,6 +107,7 @@ const composeReport = () => {
|
|
|
107
107
|
fs.writeFileSync(htmlFilePath, html);
|
|
108
108
|
console.log(`Performance ${BOLD}${GREEN}report${END} file generated`);
|
|
109
109
|
};
|
|
110
|
+
|
|
110
111
|
function replaceMarkdownContent(startMarker: string, endMarker: string, newText: string) {
|
|
111
112
|
const parentDirectory = path.resolve(__dirname, '../..'); // The path to the parent directory
|
|
112
113
|
const filePath = path.join(parentDirectory, 'README.md'); // Path to README.md file
|
|
@@ -174,10 +174,14 @@ describe('BinaryTree', () => {
|
|
|
174
174
|
|
|
175
175
|
it('should subTreeTraverse', () => {
|
|
176
176
|
tree.addMany([4, 2, 6, null, 1, 3, null, 5, null, 7]);
|
|
177
|
-
expect(tree.subTreeTraverse(node => node.key, tree.getNode(6), IterationType.ITERATIVE)).toEqual([6,3, 7]);
|
|
178
|
-
expect(tree.subTreeTraverse(node => node.key, tree.getNode(6), IterationType.RECURSIVE)).toEqual([6,3, 7]);
|
|
179
|
-
expect(
|
|
180
|
-
|
|
177
|
+
expect(tree.subTreeTraverse(node => node.key, tree.getNode(6), IterationType.ITERATIVE)).toEqual([6, 3, 7]);
|
|
178
|
+
expect(tree.subTreeTraverse(node => node.key, tree.getNode(6), IterationType.RECURSIVE)).toEqual([6, 3, 7]);
|
|
179
|
+
expect(
|
|
180
|
+
tree.subTreeTraverse(node => (node === null ? null : node.key), tree.getNode(6), IterationType.ITERATIVE, true)
|
|
181
|
+
).toEqual([6, 3, 7, null]);
|
|
182
|
+
expect(
|
|
183
|
+
tree.subTreeTraverse(node => (node === null ? null : node.key), tree.getNode(6), IterationType.RECURSIVE, true)
|
|
184
|
+
).toEqual([6, 3, 7, null]);
|
|
181
185
|
});
|
|
182
186
|
|
|
183
187
|
it('should clear the tree', () => {
|
|
@@ -268,17 +272,33 @@ describe('BinaryTree traversals', () => {
|
|
|
268
272
|
|
|
269
273
|
const arr = [35, 20, 40, 15, 29, null, 50, null, 16, 28, 30, 45, 55];
|
|
270
274
|
tree.refill(arr);
|
|
271
|
-
expect(
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
expect(
|
|
275
|
+
expect(
|
|
276
|
+
tree.bfs(node => node, tree.root, IterationType.ITERATIVE, true).map(node => (node === null ? null : node.key))
|
|
277
|
+
).toEqual([35, 20, 40, 15, 29, null, 50, null, 16, 28, 30, 45, 55]);
|
|
278
|
+
expect(
|
|
279
|
+
tree.bfs(node => node, tree.root, IterationType.RECURSIVE, true).map(node => (node === null ? null : node.key))
|
|
280
|
+
).toEqual([35, 20, 40, 15, 29, null, 50, null, 16, 28, 30, 45, 55]);
|
|
281
|
+
expect(
|
|
282
|
+
tree.bfs(node => node, tree.root, IterationType.ITERATIVE).map(node => (node === null ? null : node.key))
|
|
283
|
+
).toEqual([35, 20, 40, 15, 29, 50, 16, 28, 30, 45, 55]);
|
|
284
|
+
expect(
|
|
285
|
+
tree.bfs(node => node, tree.root, IterationType.RECURSIVE).map(node => (node === null ? null : node.key))
|
|
286
|
+
).toEqual([35, 20, 40, 15, 29, 50, 16, 28, 30, 45, 55]);
|
|
275
287
|
|
|
276
288
|
expect(tree.dfs(node => node.key, 'pre')).toEqual([35, 20, 15, 16, 29, 28, 30, 40, 50, 45, 55]);
|
|
277
289
|
expect(tree.dfs(node => node.key, 'pre', tree.root, IterationType.RECURSIVE)).toEqual([
|
|
278
290
|
35, 20, 15, 16, 29, 28, 30, 40, 50, 45, 55
|
|
279
291
|
]);
|
|
280
|
-
expect(
|
|
281
|
-
|
|
292
|
+
expect(
|
|
293
|
+
tree
|
|
294
|
+
.dfs(node => node, 'pre', tree.root, IterationType.ITERATIVE, true)
|
|
295
|
+
.map(node => (node === null ? null : node.key))
|
|
296
|
+
).toEqual([35, 20, 15, null, 16, 29, 28, 30, 40, null, 50, 45, 55]);
|
|
297
|
+
expect(
|
|
298
|
+
tree
|
|
299
|
+
.dfs(node => node, 'pre', tree.root, IterationType.RECURSIVE, true)
|
|
300
|
+
.map(node => (node === null ? null : node.key))
|
|
301
|
+
).toEqual([35, 20, 15, null, 16, 29, 28, 30, 40, null, 50, 45, 55]);
|
|
282
302
|
|
|
283
303
|
expect(tree.dfs(node => node.key, 'in')).toEqual([15, 16, 20, 28, 29, 30, 35, 40, 45, 50, 55]);
|
|
284
304
|
expect(tree.dfs(node => node.key, 'post')).toEqual([16, 15, 28, 30, 29, 20, 45, 55, 50, 40, 35]);
|
|
@@ -300,21 +320,20 @@ describe('BinaryTree traversals', () => {
|
|
|
300
320
|
[15, 29, 50],
|
|
301
321
|
[16, 28, 30, 45, 55]
|
|
302
322
|
]);
|
|
303
|
-
expect(tree.listLevels(node => node === null ? null :node.key, tree.root, IterationType.ITERATIVE, true)).toEqual([
|
|
323
|
+
expect(tree.listLevels(node => (node === null ? null : node.key), tree.root, IterationType.ITERATIVE, true)).toEqual([
|
|
304
324
|
[35],
|
|
305
325
|
[20, 40],
|
|
306
|
-
[15, 29, null,50],
|
|
326
|
+
[15, 29, null, 50],
|
|
307
327
|
[null, 16, 28, 30, 45, 55]
|
|
308
328
|
]);
|
|
309
|
-
expect(tree.listLevels(node => node === null ? null :node.key, tree.root, IterationType.RECURSIVE, true)).toEqual([
|
|
329
|
+
expect(tree.listLevels(node => (node === null ? null : node.key), tree.root, IterationType.RECURSIVE, true)).toEqual([
|
|
310
330
|
[35],
|
|
311
331
|
[20, 40],
|
|
312
|
-
[15, 29, null,50],
|
|
332
|
+
[15, 29, null, 50],
|
|
313
333
|
[null, 16, 28, 30, 45, 55]
|
|
314
334
|
]);
|
|
315
335
|
});
|
|
316
336
|
|
|
317
|
-
|
|
318
337
|
describe('BinaryTree', () => {
|
|
319
338
|
let tree: BinaryTree<string>;
|
|
320
339
|
|
|
@@ -837,4 +837,17 @@ describe('BST Performance test', function () {
|
|
|
837
837
|
bst.addMany([9, 8, 7, 3, 1, 2, 5, 4, 6], undefined, false);
|
|
838
838
|
expect(bst.lastKey()).toBe(9);
|
|
839
839
|
});
|
|
840
|
+
|
|
841
|
+
it('should subTreeTraverse, null should be ignored', () => {
|
|
842
|
+
const bst = new BST();
|
|
843
|
+
bst.addMany([4, 2, 6, null, 1, 3, null, 5, null, 7]);
|
|
844
|
+
expect(bst.subTreeTraverse(node => node.key, bst.getNode(6), IterationType.ITERATIVE)).toEqual([6, 5, 7]);
|
|
845
|
+
expect(bst.subTreeTraverse(node => node.key, bst.getNode(6), IterationType.RECURSIVE)).toEqual([6, 5, 7]);
|
|
846
|
+
expect(
|
|
847
|
+
bst.subTreeTraverse(node => (node === null ? null : node.key), bst.getNode(6), IterationType.ITERATIVE, true)
|
|
848
|
+
).toEqual([6, 5, 7]);
|
|
849
|
+
expect(
|
|
850
|
+
bst.subTreeTraverse(node => (node === null ? null : node.key), bst.getNode(6), IterationType.RECURSIVE, true)
|
|
851
|
+
).toEqual([6, 5, 7]);
|
|
852
|
+
});
|
|
840
853
|
});
|
|
@@ -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,36 @@ describe('Inherit from DirectedGraph and perform operations test2.', () => {
|
|
|
562
562
|
}
|
|
563
563
|
});
|
|
564
564
|
});
|
|
565
|
+
|
|
566
|
+
describe('cycles, strongly connected components, bridges, articular points in DirectedGraph', () => {
|
|
567
|
+
const graph = new DirectedGraph();
|
|
568
|
+
graph.addVertex('A');
|
|
569
|
+
graph.addVertex('B');
|
|
570
|
+
graph.addVertex('C');
|
|
571
|
+
graph.addVertex('D');
|
|
572
|
+
graph.addVertex('E');
|
|
573
|
+
graph.addVertex('F');
|
|
574
|
+
graph.addVertex('G');
|
|
575
|
+
graph.addVertex('H');
|
|
576
|
+
graph.addEdge('A', 'B');
|
|
577
|
+
graph.addEdge('B', 'D');
|
|
578
|
+
graph.addEdge('D', 'C');
|
|
579
|
+
graph.addEdge('C', 'A');
|
|
580
|
+
graph.addEdge('C', 'B');
|
|
581
|
+
graph.addEdge('D', 'E');
|
|
582
|
+
graph.addEdge('E', 'G');
|
|
583
|
+
graph.addEdge('E', 'H');
|
|
584
|
+
graph.addEdge('H', 'F');
|
|
585
|
+
const cycles = graph.getCycles();
|
|
586
|
+
const scCs = graph.getSCCs();
|
|
587
|
+
const bridges = graph.getBridges();
|
|
588
|
+
const cutVertexes = graph.getCutVertexes();
|
|
589
|
+
const dfnMap = graph.getDFNMap();
|
|
590
|
+
const lowMap = graph.getLowMap();
|
|
591
|
+
expect(cycles.size).toBe(1);
|
|
592
|
+
expect(scCs.size).toBe(5);
|
|
593
|
+
expect(bridges.length).toBe(4);
|
|
594
|
+
expect(cutVertexes.length).toBe(4);
|
|
595
|
+
expect(dfnMap.size).toBe(8);
|
|
596
|
+
expect(lowMap.size).toBe(8);
|
|
597
|
+
});
|