min-heap-typed 1.39.4 → 1.39.6
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/data-structures/binary-tree/avl-tree.d.ts +6 -6
- package/dist/data-structures/binary-tree/avl-tree.js +13 -13
- package/dist/data-structures/binary-tree/binary-tree.d.ts +7 -7
- package/dist/data-structures/binary-tree/binary-tree.js +17 -17
- package/dist/data-structures/binary-tree/bst.d.ts +6 -6
- package/dist/data-structures/binary-tree/bst.js +13 -13
- package/dist/data-structures/binary-tree/rb-tree.d.ts +2 -2
- package/dist/data-structures/binary-tree/rb-tree.js +4 -4
- package/dist/data-structures/binary-tree/segment-tree.d.ts +7 -7
- package/dist/data-structures/binary-tree/segment-tree.js +16 -16
- package/dist/data-structures/binary-tree/tree-multiset.d.ts +6 -6
- package/dist/data-structures/binary-tree/tree-multiset.js +18 -18
- package/dist/data-structures/graph/abstract-graph.d.ts +96 -96
- package/dist/data-structures/graph/abstract-graph.js +64 -64
- package/dist/data-structures/graph/directed-graph.d.ts +68 -68
- package/dist/data-structures/graph/directed-graph.js +48 -48
- package/dist/data-structures/graph/map-graph.d.ts +13 -13
- package/dist/data-structures/graph/map-graph.js +15 -15
- package/dist/data-structures/graph/undirected-graph.d.ts +42 -42
- package/dist/data-structures/graph/undirected-graph.js +32 -32
- package/dist/data-structures/hash/hash-table.d.ts +4 -4
- package/dist/data-structures/hash/hash-table.js +8 -8
- package/dist/data-structures/linked-list/doubly-linked-list.d.ts +31 -31
- package/dist/data-structures/linked-list/doubly-linked-list.js +54 -54
- package/dist/data-structures/linked-list/singly-linked-list.d.ts +24 -24
- package/dist/data-structures/linked-list/singly-linked-list.js +52 -52
- package/dist/data-structures/queue/queue.d.ts +1 -1
- package/dist/data-structures/queue/queue.js +4 -4
- package/dist/interfaces/binary-tree.d.ts +2 -2
- package/dist/interfaces/graph.d.ts +3 -3
- package/package.json +2 -2
- package/src/data-structures/binary-tree/avl-tree.ts +13 -13
- package/src/data-structures/binary-tree/binary-tree.ts +18 -18
- package/src/data-structures/binary-tree/bst.ts +16 -16
- package/src/data-structures/binary-tree/rb-tree.ts +6 -6
- package/src/data-structures/binary-tree/segment-tree.ts +15 -15
- package/src/data-structures/binary-tree/tree-multiset.ts +18 -18
- package/src/data-structures/graph/abstract-graph.ts +156 -154
- package/src/data-structures/graph/directed-graph.ts +99 -94
- package/src/data-structures/graph/map-graph.ts +22 -25
- package/src/data-structures/graph/undirected-graph.ts +62 -60
- package/src/data-structures/hash/hash-table.ts +9 -9
- package/src/data-structures/linked-list/doubly-linked-list.ts +61 -61
- package/src/data-structures/linked-list/singly-linked-list.ts +58 -58
- package/src/data-structures/queue/queue.ts +2 -2
- package/src/interfaces/binary-tree.ts +2 -2
- package/src/interfaces/graph.ts +3 -3
|
@@ -16,12 +16,12 @@ export abstract class AbstractVertex<V = any> {
|
|
|
16
16
|
* The function is a protected constructor that takes an key and an optional value as parameters.
|
|
17
17
|
* @param {VertexKey} key - The `key` parameter is of type `VertexKey` and represents the identifier of the vertex. It is
|
|
18
18
|
* used to uniquely identify the vertex object.
|
|
19
|
-
* @param {V} [
|
|
19
|
+
* @param {V} [value] - The parameter "value" is an optional parameter of type V. It is used to assign a value to the
|
|
20
20
|
* vertex. If no value is provided, it will be set to undefined.
|
|
21
21
|
*/
|
|
22
|
-
protected constructor(key: VertexKey,
|
|
22
|
+
protected constructor(key: VertexKey, value?: V) {
|
|
23
23
|
this._key = key;
|
|
24
|
-
this.
|
|
24
|
+
this._value = value;
|
|
25
25
|
}
|
|
26
26
|
|
|
27
27
|
private _key: VertexKey;
|
|
@@ -34,41 +34,41 @@ export abstract class AbstractVertex<V = any> {
|
|
|
34
34
|
this._key = v;
|
|
35
35
|
}
|
|
36
36
|
|
|
37
|
-
private
|
|
37
|
+
private _value: V | undefined;
|
|
38
38
|
|
|
39
|
-
get
|
|
40
|
-
return this.
|
|
39
|
+
get value(): V | undefined {
|
|
40
|
+
return this._value;
|
|
41
41
|
}
|
|
42
42
|
|
|
43
|
-
set
|
|
44
|
-
this.
|
|
43
|
+
set value(value: V | undefined) {
|
|
44
|
+
this._value = value;
|
|
45
45
|
}
|
|
46
46
|
}
|
|
47
47
|
|
|
48
|
-
export abstract class AbstractEdge<
|
|
48
|
+
export abstract class AbstractEdge<E = any> {
|
|
49
49
|
/**
|
|
50
50
|
* The above function is a protected constructor that initializes the weight, value, and hash code properties of an
|
|
51
51
|
* object.
|
|
52
52
|
* @param {number} [weight] - The `weight` parameter is an optional number that represents the weight of the object. If
|
|
53
53
|
* a value is provided, it will be assigned to the `_weight` property. If no value is provided, the default value of 1
|
|
54
54
|
* will be assigned.
|
|
55
|
-
* @param {
|
|
55
|
+
* @param {VO} [value] - The `value` parameter is of type `VO`, which means it can be any type. It is an optional parameter,
|
|
56
56
|
* meaning it can be omitted when creating an instance of the class.
|
|
57
57
|
*/
|
|
58
|
-
protected constructor(weight?: number,
|
|
58
|
+
protected constructor(weight?: number, value?: E) {
|
|
59
59
|
this._weight = weight !== undefined ? weight : 1;
|
|
60
|
-
this.
|
|
60
|
+
this._value = value;
|
|
61
61
|
this._hashCode = uuidV4();
|
|
62
62
|
}
|
|
63
63
|
|
|
64
|
-
private
|
|
64
|
+
private _value: E | undefined;
|
|
65
65
|
|
|
66
|
-
get
|
|
67
|
-
return this.
|
|
66
|
+
get value(): E | undefined {
|
|
67
|
+
return this._value;
|
|
68
68
|
}
|
|
69
69
|
|
|
70
|
-
set
|
|
71
|
-
this.
|
|
70
|
+
set value(value: E | undefined) {
|
|
71
|
+
this._value = value;
|
|
72
72
|
}
|
|
73
73
|
|
|
74
74
|
private _weight: number;
|
|
@@ -103,13 +103,15 @@ export abstract class AbstractEdge<V = any> {
|
|
|
103
103
|
}
|
|
104
104
|
|
|
105
105
|
export abstract class AbstractGraph<
|
|
106
|
-
V
|
|
107
|
-
E
|
|
108
|
-
>
|
|
106
|
+
V = any,
|
|
107
|
+
E = any,
|
|
108
|
+
VO extends AbstractVertex<V> = AbstractVertex<V>,
|
|
109
|
+
EO extends AbstractEdge<E> = AbstractEdge<E>
|
|
110
|
+
> implements IGraph<V, E, VO, EO>
|
|
109
111
|
{
|
|
110
|
-
private _vertices: Map<VertexKey,
|
|
112
|
+
private _vertices: Map<VertexKey, VO> = new Map<VertexKey, VO>();
|
|
111
113
|
|
|
112
|
-
get vertices(): Map<VertexKey,
|
|
114
|
+
get vertices(): Map<VertexKey, VO> {
|
|
113
115
|
return this._vertices;
|
|
114
116
|
}
|
|
115
117
|
|
|
@@ -117,9 +119,9 @@ export abstract class AbstractGraph<
|
|
|
117
119
|
* In TypeScript, a subclass inherits the interface implementation of its parent class, without needing to implement the same interface again in the subclass. This behavior differs from Java's approach. In Java, if a parent class implements an interface, the subclass needs to explicitly implement the same interface, even if the parent class has already implemented it.
|
|
118
120
|
* This means that using abstract methods in the parent class cannot constrain the grandchild classes. Defining methods within an interface also cannot constrain the descendant classes. When inheriting from this class, developers need to be aware that this method needs to be overridden.
|
|
119
121
|
* @param key
|
|
120
|
-
* @param
|
|
122
|
+
* @param value
|
|
121
123
|
*/
|
|
122
|
-
abstract createVertex(key: VertexKey,
|
|
124
|
+
abstract createVertex(key: VertexKey, value?: V): VO;
|
|
123
125
|
|
|
124
126
|
/**
|
|
125
127
|
* In TypeScript, a subclass inherits the interface implementation of its parent class, without needing to implement the same interface again in the subclass. This behavior differs from Java's approach. In Java, if a parent class implements an interface, the subclass needs to explicitly implement the same interface, even if the parent class has already implemented it.
|
|
@@ -127,23 +129,23 @@ export abstract class AbstractGraph<
|
|
|
127
129
|
* @param srcOrV1
|
|
128
130
|
* @param destOrV2
|
|
129
131
|
* @param weight
|
|
130
|
-
* @param
|
|
132
|
+
* @param value
|
|
131
133
|
*/
|
|
132
|
-
abstract createEdge(srcOrV1: VertexKey
|
|
134
|
+
abstract createEdge(srcOrV1: VertexKey, destOrV2: VertexKey, weight?: number, value?: E): EO;
|
|
133
135
|
|
|
134
|
-
abstract deleteEdge(edge:
|
|
136
|
+
abstract deleteEdge(edge: EO): EO | null;
|
|
135
137
|
|
|
136
|
-
abstract getEdge(srcOrKey:
|
|
138
|
+
abstract getEdge(srcOrKey: VO | VertexKey, destOrKey: VO | VertexKey): EO | null;
|
|
137
139
|
|
|
138
|
-
abstract degreeOf(vertexOrKey:
|
|
140
|
+
abstract degreeOf(vertexOrKey: VO | VertexKey): number;
|
|
139
141
|
|
|
140
|
-
abstract edgeSet():
|
|
142
|
+
abstract edgeSet(): EO[];
|
|
141
143
|
|
|
142
|
-
abstract edgesOf(vertexOrKey:
|
|
144
|
+
abstract edgesOf(vertexOrKey: VO | VertexKey): EO[];
|
|
143
145
|
|
|
144
|
-
abstract getNeighbors(vertexOrKey:
|
|
146
|
+
abstract getNeighbors(vertexOrKey: VO | VertexKey): VO[];
|
|
145
147
|
|
|
146
|
-
abstract getEndsOfEdge(edge:
|
|
148
|
+
abstract getEndsOfEdge(edge: EO): [VO, VO] | null;
|
|
147
149
|
|
|
148
150
|
/**
|
|
149
151
|
* The function "getVertex" returns the vertex with the specified ID or null if it doesn't exist.
|
|
@@ -152,52 +154,52 @@ export abstract class AbstractGraph<
|
|
|
152
154
|
* @returns The method `getVertex` returns the vertex with the specified `vertexKey` if it exists in the `_vertices`
|
|
153
155
|
* map. If the vertex does not exist, it returns `null`.
|
|
154
156
|
*/
|
|
155
|
-
getVertex(vertexKey: VertexKey):
|
|
157
|
+
getVertex(vertexKey: VertexKey): VO | null {
|
|
156
158
|
return this._vertices.get(vertexKey) || null;
|
|
157
159
|
}
|
|
158
160
|
|
|
159
161
|
/**
|
|
160
162
|
* The function checks if a vertex exists in a graph.
|
|
161
|
-
* @param {
|
|
163
|
+
* @param {VO | VertexKey} vertexOrKey - The parameter `vertexOrKey` can be either a vertex object (`VO`) or a vertex ID
|
|
162
164
|
* (`VertexKey`).
|
|
163
165
|
* @returns a boolean value.
|
|
164
166
|
*/
|
|
165
|
-
hasVertex(vertexOrKey:
|
|
167
|
+
hasVertex(vertexOrKey: VO | VertexKey): boolean {
|
|
166
168
|
return this._vertices.has(this._getVertexKey(vertexOrKey));
|
|
167
169
|
}
|
|
168
170
|
|
|
169
|
-
addVertex(vertex:
|
|
171
|
+
addVertex(vertex: VO): boolean;
|
|
170
172
|
|
|
171
|
-
addVertex(key: VertexKey,
|
|
173
|
+
addVertex(key: VertexKey, value?: V): boolean;
|
|
172
174
|
|
|
173
|
-
addVertex(keyOrVertex: VertexKey |
|
|
175
|
+
addVertex(keyOrVertex: VertexKey | VO, value?: V): boolean {
|
|
174
176
|
if (keyOrVertex instanceof AbstractVertex) {
|
|
175
177
|
return this._addVertexOnly(keyOrVertex);
|
|
176
178
|
} else {
|
|
177
|
-
const newVertex = this.createVertex(keyOrVertex,
|
|
179
|
+
const newVertex = this.createVertex(keyOrVertex, value);
|
|
178
180
|
return this._addVertexOnly(newVertex);
|
|
179
181
|
}
|
|
180
182
|
}
|
|
181
183
|
|
|
182
184
|
/**
|
|
183
185
|
* The `deleteVertex` function removes a vertex from a graph by its ID or by the vertex object itself.
|
|
184
|
-
* @param {
|
|
186
|
+
* @param {VO | VertexKey} vertexOrKey - The parameter `vertexOrKey` can be either a vertex object (`VO`) or a vertex ID
|
|
185
187
|
* (`VertexKey`).
|
|
186
188
|
* @returns The method is returning a boolean value.
|
|
187
189
|
*/
|
|
188
|
-
deleteVertex(vertexOrKey:
|
|
190
|
+
deleteVertex(vertexOrKey: VO | VertexKey): boolean {
|
|
189
191
|
const vertexKey = this._getVertexKey(vertexOrKey);
|
|
190
192
|
return this._vertices.delete(vertexKey);
|
|
191
193
|
}
|
|
192
194
|
|
|
193
195
|
/**
|
|
194
196
|
* The function removes all vertices from a graph and returns a boolean indicating if any vertices were removed.
|
|
195
|
-
* @param {
|
|
197
|
+
* @param {VO[] | VertexKey[]} vertices - The `vertices` parameter can be either an array of vertices (`VO[]`) or an array
|
|
196
198
|
* of vertex IDs (`VertexKey[]`).
|
|
197
199
|
* @returns a boolean value. It returns true if at least one vertex was successfully removed, and false if no vertices
|
|
198
200
|
* were removed.
|
|
199
201
|
*/
|
|
200
|
-
removeManyVertices(vertices:
|
|
202
|
+
removeManyVertices(vertices: VO[] | VertexKey[]): boolean {
|
|
201
203
|
const removed: boolean[] = [];
|
|
202
204
|
for (const v of vertices) {
|
|
203
205
|
removed.push(this.deleteVertex(v));
|
|
@@ -207,22 +209,22 @@ export abstract class AbstractGraph<
|
|
|
207
209
|
|
|
208
210
|
/**
|
|
209
211
|
* The function checks if there is an edge between two vertices and returns a boolean value indicating the result.
|
|
210
|
-
* @param {VertexKey |
|
|
211
|
-
* identifier of a vertex in a graph, while
|
|
212
|
-
* @param {VertexKey |
|
|
213
|
-
* `VertexKey` or a `
|
|
212
|
+
* @param {VertexKey | VO} v1 - The parameter v1 can be either a VertexKey or a VO. A VertexKey represents the unique
|
|
213
|
+
* identifier of a vertex in a graph, while VO represents the type of the vertex object itself.
|
|
214
|
+
* @param {VertexKey | VO} v2 - The parameter `v2` represents the second vertex in the edge. It can be either a
|
|
215
|
+
* `VertexKey` or a `VO` type, which represents the type of the vertex.
|
|
214
216
|
* @returns A boolean value is being returned.
|
|
215
217
|
*/
|
|
216
|
-
hasEdge(v1: VertexKey |
|
|
218
|
+
hasEdge(v1: VertexKey | VO, v2: VertexKey | VO): boolean {
|
|
217
219
|
const edge = this.getEdge(v1, v2);
|
|
218
220
|
return !!edge;
|
|
219
221
|
}
|
|
220
222
|
|
|
221
|
-
addEdge(edge:
|
|
223
|
+
addEdge(edge: EO): boolean;
|
|
222
224
|
|
|
223
|
-
addEdge(src:
|
|
225
|
+
addEdge(src: VO | VertexKey, dest: VO | VertexKey, weight?: number, value?: E): boolean;
|
|
224
226
|
|
|
225
|
-
addEdge(srcOrEdge:
|
|
227
|
+
addEdge(srcOrEdge: VO | VertexKey | EO, dest?: VO | VertexKey, weight?: number, value?: E): boolean {
|
|
226
228
|
if (srcOrEdge instanceof AbstractEdge) {
|
|
227
229
|
return this._addEdgeOnly(srcOrEdge);
|
|
228
230
|
} else {
|
|
@@ -230,7 +232,7 @@ export abstract class AbstractGraph<
|
|
|
230
232
|
if (!(this.hasVertex(srcOrEdge) && this.hasVertex(dest))) return false;
|
|
231
233
|
if (srcOrEdge instanceof AbstractVertex) srcOrEdge = srcOrEdge.key;
|
|
232
234
|
if (dest instanceof AbstractVertex) dest = dest.key;
|
|
233
|
-
const newEdge = this.createEdge(srcOrEdge, dest, weight,
|
|
235
|
+
const newEdge = this.createEdge(srcOrEdge, dest, weight, value);
|
|
234
236
|
return this._addEdgeOnly(newEdge);
|
|
235
237
|
} else {
|
|
236
238
|
throw new Error('dest must be a Vertex or vertex key while srcOrEdge is an Edge');
|
|
@@ -240,16 +242,16 @@ export abstract class AbstractGraph<
|
|
|
240
242
|
|
|
241
243
|
/**
|
|
242
244
|
* The function sets the weight of an edge between two vertices in a graph.
|
|
243
|
-
* @param {VertexKey |
|
|
245
|
+
* @param {VertexKey | VO} srcOrKey - The `srcOrKey` parameter can be either a `VertexKey` or a `VO` object. It represents
|
|
244
246
|
* the source vertex of the edge.
|
|
245
|
-
* @param {VertexKey |
|
|
246
|
-
* either a `VertexKey` or a vertex object `
|
|
247
|
+
* @param {VertexKey | VO} destOrKey - The `destOrKey` parameter represents the destination vertex of the edge. It can be
|
|
248
|
+
* either a `VertexKey` or a vertex object `VO`.
|
|
247
249
|
* @param {number} weight - The weight parameter represents the weight of the edge between the source vertex (srcOrKey)
|
|
248
250
|
* and the destination vertex (destOrKey).
|
|
249
251
|
* @returns a boolean value. If the edge exists between the source and destination vertices, the function will update
|
|
250
252
|
* the weight of the edge and return true. If the edge does not exist, the function will return false.
|
|
251
253
|
*/
|
|
252
|
-
setEdgeWeight(srcOrKey: VertexKey |
|
|
254
|
+
setEdgeWeight(srcOrKey: VertexKey | VO, destOrKey: VertexKey | VO, weight: number): boolean {
|
|
253
255
|
const edge = this.getEdge(srcOrKey, destOrKey);
|
|
254
256
|
if (edge) {
|
|
255
257
|
edge.weight = weight;
|
|
@@ -261,20 +263,20 @@ export abstract class AbstractGraph<
|
|
|
261
263
|
|
|
262
264
|
/**
|
|
263
265
|
* The function `getAllPathsBetween` finds all paths between two vertices in a graph using depth-first search.
|
|
264
|
-
* @param {
|
|
266
|
+
* @param {VO | VertexKey} v1 - The parameter `v1` represents either a vertex object (`VO`) or a vertex ID (`VertexKey`).
|
|
265
267
|
* It is the starting vertex for finding paths.
|
|
266
|
-
* @param {
|
|
267
|
-
* @returns The function `getAllPathsBetween` returns an array of arrays of vertices (`
|
|
268
|
+
* @param {VO | VertexKey} v2 - The parameter `v2` represents either a vertex object (`VO`) or a vertex ID (`VertexKey`).
|
|
269
|
+
* @returns The function `getAllPathsBetween` returns an array of arrays of vertices (`VO[][]`).
|
|
268
270
|
*/
|
|
269
|
-
getAllPathsBetween(v1:
|
|
270
|
-
const paths:
|
|
271
|
+
getAllPathsBetween(v1: VO | VertexKey, v2: VO | VertexKey): VO[][] {
|
|
272
|
+
const paths: VO[][] = [];
|
|
271
273
|
const vertex1 = this._getVertex(v1);
|
|
272
274
|
const vertex2 = this._getVertex(v2);
|
|
273
275
|
if (!(vertex1 && vertex2)) {
|
|
274
276
|
return [];
|
|
275
277
|
}
|
|
276
278
|
|
|
277
|
-
const dfs = (cur:
|
|
279
|
+
const dfs = (cur: VO, dest: VO, visiting: Map<VO, boolean>, path: VO[]) => {
|
|
278
280
|
visiting.set(cur, true);
|
|
279
281
|
|
|
280
282
|
if (cur === dest) {
|
|
@@ -286,23 +288,23 @@ export abstract class AbstractGraph<
|
|
|
286
288
|
if (!visiting.get(neighbor)) {
|
|
287
289
|
path.push(neighbor);
|
|
288
290
|
dfs(neighbor, dest, visiting, path);
|
|
289
|
-
arrayRemove(path, (vertex:
|
|
291
|
+
arrayRemove(path, (vertex: VO) => vertex === neighbor);
|
|
290
292
|
}
|
|
291
293
|
}
|
|
292
294
|
|
|
293
295
|
visiting.set(cur, false);
|
|
294
296
|
};
|
|
295
297
|
|
|
296
|
-
dfs(vertex1, vertex2, new Map<
|
|
298
|
+
dfs(vertex1, vertex2, new Map<VO, boolean>(), []);
|
|
297
299
|
return paths;
|
|
298
300
|
}
|
|
299
301
|
|
|
300
302
|
/**
|
|
301
303
|
* The function calculates the sum of weights along a given path.
|
|
302
|
-
* @param {
|
|
304
|
+
* @param {VO[]} path - An array of vertices (VO) representing a path in a graph.
|
|
303
305
|
* @returns The function `getPathSumWeight` returns the sum of the weights of the edges in the given path.
|
|
304
306
|
*/
|
|
305
|
-
getPathSumWeight(path:
|
|
307
|
+
getPathSumWeight(path: VO[]): number {
|
|
306
308
|
let sum = 0;
|
|
307
309
|
for (let i = 0; i < path.length; i++) {
|
|
308
310
|
sum += this.getEdge(path[i], path[i + 1])?.weight || 0;
|
|
@@ -313,8 +315,8 @@ export abstract class AbstractGraph<
|
|
|
313
315
|
/**
|
|
314
316
|
* The function `getMinCostBetween` calculates the minimum cost between two vertices in a graph, either based on edge
|
|
315
317
|
* weights or using a breadth-first search algorithm.
|
|
316
|
-
* @param {
|
|
317
|
-
* @param {
|
|
318
|
+
* @param {VO | VertexKey} v1 - The parameter `v1` represents the starting vertex or its ID.
|
|
319
|
+
* @param {VO | VertexKey} v2 - The parameter `v2` represents the destination vertex or its ID. It is the vertex to which
|
|
318
320
|
* you want to find the minimum cost or weight from the source vertex `v1`.
|
|
319
321
|
* @param {boolean} [isWeight] - isWeight is an optional parameter that indicates whether the graph edges have weights.
|
|
320
322
|
* If isWeight is set to true, the function will calculate the minimum cost between v1 and v2 based on the weights of
|
|
@@ -324,7 +326,7 @@ export abstract class AbstractGraph<
|
|
|
324
326
|
* vertices. If `isWeight` is `false` or not provided, it uses a breadth-first search (BFS) algorithm to calculate the
|
|
325
327
|
* minimum number of
|
|
326
328
|
*/
|
|
327
|
-
getMinCostBetween(v1:
|
|
329
|
+
getMinCostBetween(v1: VO | VertexKey, v2: VO | VertexKey, isWeight?: boolean): number | null {
|
|
328
330
|
if (isWeight === undefined) isWeight = false;
|
|
329
331
|
|
|
330
332
|
if (isWeight) {
|
|
@@ -342,8 +344,8 @@ export abstract class AbstractGraph<
|
|
|
342
344
|
return null;
|
|
343
345
|
}
|
|
344
346
|
|
|
345
|
-
const visited: Map<
|
|
346
|
-
const queue = new Queue<
|
|
347
|
+
const visited: Map<VO, boolean> = new Map();
|
|
348
|
+
const queue = new Queue<VO>([vertex1]);
|
|
347
349
|
visited.set(vertex1, true);
|
|
348
350
|
let cost = 0;
|
|
349
351
|
while (queue.size > 0) {
|
|
@@ -372,17 +374,17 @@ export abstract class AbstractGraph<
|
|
|
372
374
|
/**
|
|
373
375
|
* The function `getMinPathBetween` returns the minimum path between two vertices in a graph, either based on weight or
|
|
374
376
|
* using a breadth-first search algorithm.
|
|
375
|
-
* @param {
|
|
376
|
-
* object (`
|
|
377
|
-
* @param {
|
|
377
|
+
* @param {VO | VertexKey} v1 - The parameter `v1` represents the starting vertex of the path. It can be either a vertex
|
|
378
|
+
* object (`VO`) or a vertex ID (`VertexKey`).
|
|
379
|
+
* @param {VO | VertexKey} v2 - VO | VertexKey - The second vertex or vertex ID between which we want to find the minimum
|
|
378
380
|
* path.
|
|
379
381
|
* @param {boolean} [isWeight] - A boolean flag indicating whether to consider the weight of edges in finding the
|
|
380
382
|
* minimum path. If set to true, the function will use Dijkstra's algorithm to find the minimum weighted path. If set
|
|
381
383
|
* to false, the function will use breadth-first search (BFS) to find the minimum path.
|
|
382
|
-
* @returns The function `getMinPathBetween` returns an array of vertices (`
|
|
384
|
+
* @returns The function `getMinPathBetween` returns an array of vertices (`VO[]`) representing the minimum path between
|
|
383
385
|
* two vertices (`v1` and `v2`). If there is no path between the vertices, it returns `null`.
|
|
384
386
|
*/
|
|
385
|
-
getMinPathBetween(v1:
|
|
387
|
+
getMinPathBetween(v1: VO | VertexKey, v2: VO | VertexKey, isWeight?: boolean): VO[] | null {
|
|
386
388
|
if (isWeight === undefined) isWeight = false;
|
|
387
389
|
|
|
388
390
|
if (isWeight) {
|
|
@@ -401,14 +403,14 @@ export abstract class AbstractGraph<
|
|
|
401
403
|
return allPaths[minIndex] || null;
|
|
402
404
|
} else {
|
|
403
405
|
// BFS
|
|
404
|
-
let minPath:
|
|
406
|
+
let minPath: VO[] = [];
|
|
405
407
|
const vertex1 = this._getVertex(v1);
|
|
406
408
|
const vertex2 = this._getVertex(v2);
|
|
407
409
|
if (!(vertex1 && vertex2)) {
|
|
408
410
|
return [];
|
|
409
411
|
}
|
|
410
412
|
|
|
411
|
-
const dfs = (cur:
|
|
413
|
+
const dfs = (cur: VO, dest: VO, visiting: Map<VO, boolean>, path: VO[]) => {
|
|
412
414
|
visiting.set(cur, true);
|
|
413
415
|
|
|
414
416
|
if (cur === dest) {
|
|
@@ -421,29 +423,29 @@ export abstract class AbstractGraph<
|
|
|
421
423
|
if (!visiting.get(neighbor)) {
|
|
422
424
|
path.push(neighbor);
|
|
423
425
|
dfs(neighbor, dest, visiting, path);
|
|
424
|
-
arrayRemove(path, (vertex:
|
|
426
|
+
arrayRemove(path, (vertex: VO) => vertex === neighbor);
|
|
425
427
|
}
|
|
426
428
|
}
|
|
427
429
|
|
|
428
430
|
visiting.set(cur, false);
|
|
429
431
|
};
|
|
430
432
|
|
|
431
|
-
dfs(vertex1, vertex2, new Map<
|
|
433
|
+
dfs(vertex1, vertex2, new Map<VO, boolean>(), []);
|
|
432
434
|
return minPath;
|
|
433
435
|
}
|
|
434
436
|
}
|
|
435
437
|
|
|
436
438
|
/**
|
|
437
|
-
* Dijkstra algorithm time: O(VE) space: O(
|
|
439
|
+
* Dijkstra algorithm time: O(VE) space: O(VO + EO)
|
|
438
440
|
* /
|
|
439
441
|
|
|
440
442
|
/**
|
|
441
|
-
* Dijkstra algorithm time: O(VE) space: O(
|
|
443
|
+
* Dijkstra algorithm time: O(VE) space: O(VO + EO)
|
|
442
444
|
* The function `dijkstraWithoutHeap` implements Dijkstra's algorithm to find the shortest path between two vertices in
|
|
443
445
|
* a graph without using a heap data structure.
|
|
444
|
-
* @param {
|
|
446
|
+
* @param {VO | VertexKey} src - The source vertex from which to start the Dijkstra's algorithm. It can be either a
|
|
445
447
|
* vertex object or a vertex ID.
|
|
446
|
-
* @param {
|
|
448
|
+
* @param {VO | VertexKey | null} [dest] - The `dest` parameter in the `dijkstraWithoutHeap` function is an optional
|
|
447
449
|
* parameter that specifies the destination vertex for the Dijkstra algorithm. It can be either a vertex object or its
|
|
448
450
|
* identifier. If no destination is provided, the value is set to `null`.
|
|
449
451
|
* @param {boolean} [getMinDist] - The `getMinDist` parameter is a boolean flag that determines whether the minimum
|
|
@@ -452,27 +454,27 @@ export abstract class AbstractGraph<
|
|
|
452
454
|
* @param {boolean} [genPaths] - The `genPaths` parameter is a boolean flag that determines whether or not to generate
|
|
453
455
|
* paths in the Dijkstra algorithm. If `genPaths` is set to `true`, the algorithm will calculate and return the
|
|
454
456
|
* shortest paths from the source vertex to all other vertices in the graph. If `genPaths
|
|
455
|
-
* @returns The function `dijkstraWithoutHeap` returns an object of type `DijkstraResult<
|
|
457
|
+
* @returns The function `dijkstraWithoutHeap` returns an object of type `DijkstraResult<VO>`.
|
|
456
458
|
*/
|
|
457
459
|
dijkstraWithoutHeap(
|
|
458
|
-
src:
|
|
459
|
-
dest?:
|
|
460
|
+
src: VO | VertexKey,
|
|
461
|
+
dest?: VO | VertexKey | null,
|
|
460
462
|
getMinDist?: boolean,
|
|
461
463
|
genPaths?: boolean
|
|
462
|
-
): DijkstraResult<
|
|
464
|
+
): DijkstraResult<VO> {
|
|
463
465
|
if (getMinDist === undefined) getMinDist = false;
|
|
464
466
|
if (genPaths === undefined) genPaths = false;
|
|
465
467
|
|
|
466
468
|
if (dest === undefined) dest = null;
|
|
467
469
|
let minDist = Infinity;
|
|
468
|
-
let minDest:
|
|
469
|
-
let minPath:
|
|
470
|
-
const paths:
|
|
470
|
+
let minDest: VO | null = null;
|
|
471
|
+
let minPath: VO[] = [];
|
|
472
|
+
const paths: VO[][] = [];
|
|
471
473
|
|
|
472
474
|
const vertices = this._vertices;
|
|
473
|
-
const distMap: Map<
|
|
474
|
-
const seen: Set<
|
|
475
|
-
const preMap: Map<
|
|
475
|
+
const distMap: Map<VO, number> = new Map();
|
|
476
|
+
const seen: Set<VO> = new Set();
|
|
477
|
+
const preMap: Map<VO, VO | null> = new Map(); // predecessor
|
|
476
478
|
const srcVertex = this._getVertex(src);
|
|
477
479
|
|
|
478
480
|
const destVertex = dest ? this._getVertex(dest) : null;
|
|
@@ -490,11 +492,11 @@ export abstract class AbstractGraph<
|
|
|
490
492
|
|
|
491
493
|
const getMinOfNoSeen = () => {
|
|
492
494
|
let min = Infinity;
|
|
493
|
-
let minV:
|
|
494
|
-
for (const [key,
|
|
495
|
+
let minV: VO | null = null;
|
|
496
|
+
for (const [key, value] of distMap) {
|
|
495
497
|
if (!seen.has(key)) {
|
|
496
|
-
if (
|
|
497
|
-
min =
|
|
498
|
+
if (value < min) {
|
|
499
|
+
min = value;
|
|
498
500
|
minV = key;
|
|
499
501
|
}
|
|
500
502
|
}
|
|
@@ -502,12 +504,12 @@ export abstract class AbstractGraph<
|
|
|
502
504
|
return minV;
|
|
503
505
|
};
|
|
504
506
|
|
|
505
|
-
const getPaths = (minV:
|
|
507
|
+
const getPaths = (minV: VO | null) => {
|
|
506
508
|
for (const vertex of vertices) {
|
|
507
509
|
const vertexOrKey = vertex[1];
|
|
508
510
|
|
|
509
511
|
if (vertexOrKey instanceof AbstractVertex) {
|
|
510
|
-
const path:
|
|
512
|
+
const path: VO[] = [vertexOrKey];
|
|
511
513
|
let parent = preMap.get(vertexOrKey);
|
|
512
514
|
while (parent) {
|
|
513
515
|
path.push(parent);
|
|
@@ -569,11 +571,11 @@ export abstract class AbstractGraph<
|
|
|
569
571
|
}
|
|
570
572
|
|
|
571
573
|
/**
|
|
572
|
-
* Dijkstra algorithm time: O(logVE) space: O(
|
|
574
|
+
* Dijkstra algorithm time: O(logVE) space: O(VO + EO)
|
|
573
575
|
*
|
|
574
576
|
* Dijkstra's algorithm only solves the single-source shortest path problem, while the Bellman-Ford algorithm and Floyd-Warshall algorithm can address shortest paths between all pairs of nodes.
|
|
575
577
|
* Dijkstra's algorithm is suitable for graphs with non-negative edge weights, whereas the Bellman-Ford algorithm and Floyd-Warshall algorithm can handle negative-weight edges.
|
|
576
|
-
* The time complexity of Dijkstra's algorithm and the Bellman-Ford algorithm depends on the size of the graph, while the time complexity of the Floyd-Warshall algorithm is O(
|
|
578
|
+
* The time complexity of Dijkstra's algorithm and the Bellman-Ford algorithm depends on the size of the graph, while the time complexity of the Floyd-Warshall algorithm is O(VO^3), where VO is the number of nodes. For dense graphs, Floyd-Warshall might become slower.
|
|
577
579
|
*
|
|
578
580
|
* /
|
|
579
581
|
|
|
@@ -581,9 +583,9 @@ export abstract class AbstractGraph<
|
|
|
581
583
|
* Dijkstra's algorithm is used to find the shortest paths from a source node to all other nodes in a graph. Its basic idea is to repeatedly choose the node closest to the source node and update the distances of other nodes using this node as an intermediary. Dijkstra's algorithm requires that the edge weights in the graph are non-negative.
|
|
582
584
|
* The `dijkstra` function implements Dijkstra's algorithm to find the shortest path between a source vertex and an
|
|
583
585
|
* optional destination vertex, and optionally returns the minimum distance, the paths, and other information.
|
|
584
|
-
* @param {
|
|
586
|
+
* @param {VO | VertexKey} src - The `src` parameter represents the source vertex from which the Dijkstra algorithm will
|
|
585
587
|
* start. It can be either a vertex object or a vertex ID.
|
|
586
|
-
* @param {
|
|
588
|
+
* @param {VO | VertexKey | null} [dest] - The `dest` parameter is the destination vertex or vertex ID. It specifies the
|
|
587
589
|
* vertex to which the shortest path is calculated from the source vertex. If no destination is provided, the algorithm
|
|
588
590
|
* will calculate the shortest paths to all other vertices from the source vertex.
|
|
589
591
|
* @param {boolean} [getMinDist] - The `getMinDist` parameter is a boolean flag that determines whether the minimum
|
|
@@ -592,26 +594,26 @@ export abstract class AbstractGraph<
|
|
|
592
594
|
* @param {boolean} [genPaths] - The `genPaths` parameter is a boolean flag that determines whether or not to generate
|
|
593
595
|
* paths in the Dijkstra algorithm. If `genPaths` is set to `true`, the algorithm will calculate and return the
|
|
594
596
|
* shortest paths from the source vertex to all other vertices in the graph. If `genPaths
|
|
595
|
-
* @returns The function `dijkstra` returns an object of type `DijkstraResult<
|
|
597
|
+
* @returns The function `dijkstra` returns an object of type `DijkstraResult<VO>`.
|
|
596
598
|
*/
|
|
597
599
|
dijkstra(
|
|
598
|
-
src:
|
|
599
|
-
dest?:
|
|
600
|
+
src: VO | VertexKey,
|
|
601
|
+
dest?: VO | VertexKey | null,
|
|
600
602
|
getMinDist?: boolean,
|
|
601
603
|
genPaths?: boolean
|
|
602
|
-
): DijkstraResult<
|
|
604
|
+
): DijkstraResult<VO> {
|
|
603
605
|
if (getMinDist === undefined) getMinDist = false;
|
|
604
606
|
if (genPaths === undefined) genPaths = false;
|
|
605
607
|
|
|
606
608
|
if (dest === undefined) dest = null;
|
|
607
609
|
let minDist = Infinity;
|
|
608
|
-
let minDest:
|
|
609
|
-
let minPath:
|
|
610
|
-
const paths:
|
|
610
|
+
let minDest: VO | null = null;
|
|
611
|
+
let minPath: VO[] = [];
|
|
612
|
+
const paths: VO[][] = [];
|
|
611
613
|
const vertices = this._vertices;
|
|
612
|
-
const distMap: Map<
|
|
613
|
-
const seen: Set<
|
|
614
|
-
const preMap: Map<
|
|
614
|
+
const distMap: Map<VO, number> = new Map();
|
|
615
|
+
const seen: Set<VO> = new Set();
|
|
616
|
+
const preMap: Map<VO, VO | null> = new Map(); // predecessor
|
|
615
617
|
|
|
616
618
|
const srcVertex = this._getVertex(src);
|
|
617
619
|
const destVertex = dest ? this._getVertex(dest) : null;
|
|
@@ -623,22 +625,22 @@ export abstract class AbstractGraph<
|
|
|
623
625
|
if (vertexOrKey instanceof AbstractVertex) distMap.set(vertexOrKey, Infinity);
|
|
624
626
|
}
|
|
625
627
|
|
|
626
|
-
const heap = new PriorityQueue<{key: number;
|
|
627
|
-
heap.add({key: 0,
|
|
628
|
+
const heap = new PriorityQueue<{key: number; value: VO}>({comparator: (a, b) => a.key - b.key});
|
|
629
|
+
heap.add({key: 0, value: srcVertex});
|
|
628
630
|
|
|
629
631
|
distMap.set(srcVertex, 0);
|
|
630
632
|
preMap.set(srcVertex, null);
|
|
631
633
|
|
|
632
634
|
/**
|
|
633
635
|
* The function `getPaths` retrieves all paths from vertices to a specified minimum vertex.
|
|
634
|
-
* @param {
|
|
636
|
+
* @param {VO | null} minV - The parameter `minV` is of type `VO | null`. It represents the minimum vertex value or
|
|
635
637
|
* null.
|
|
636
638
|
*/
|
|
637
|
-
const getPaths = (minV:
|
|
639
|
+
const getPaths = (minV: VO | null) => {
|
|
638
640
|
for (const vertex of vertices) {
|
|
639
641
|
const vertexOrKey = vertex[1];
|
|
640
642
|
if (vertexOrKey instanceof AbstractVertex) {
|
|
641
|
-
const path:
|
|
643
|
+
const path: VO[] = [vertexOrKey];
|
|
642
644
|
let parent = preMap.get(vertexOrKey);
|
|
643
645
|
while (parent) {
|
|
644
646
|
path.push(parent);
|
|
@@ -654,7 +656,7 @@ export abstract class AbstractGraph<
|
|
|
654
656
|
while (heap.size > 0) {
|
|
655
657
|
const curHeapNode = heap.poll();
|
|
656
658
|
const dist = curHeapNode?.key;
|
|
657
|
-
const cur = curHeapNode?.
|
|
659
|
+
const cur = curHeapNode?.value;
|
|
658
660
|
if (dist !== undefined) {
|
|
659
661
|
if (cur) {
|
|
660
662
|
seen.add(cur);
|
|
@@ -675,7 +677,7 @@ export abstract class AbstractGraph<
|
|
|
675
677
|
const distSrcToNeighbor = distMap.get(neighbor);
|
|
676
678
|
if (distSrcToNeighbor) {
|
|
677
679
|
if (dist + weight < distSrcToNeighbor) {
|
|
678
|
-
heap.add({key: dist + weight,
|
|
680
|
+
heap.add({key: dist + weight, value: neighbor});
|
|
679
681
|
preMap.set(neighbor, cur);
|
|
680
682
|
distMap.set(neighbor, dist + weight);
|
|
681
683
|
}
|
|
@@ -706,17 +708,17 @@ export abstract class AbstractGraph<
|
|
|
706
708
|
}
|
|
707
709
|
|
|
708
710
|
/**
|
|
709
|
-
* BellmanFord time:O(VE) space:O(
|
|
711
|
+
* BellmanFord time:O(VE) space:O(VO)
|
|
710
712
|
* one to rest pairs
|
|
711
713
|
* /
|
|
712
714
|
|
|
713
715
|
/**
|
|
714
|
-
* BellmanFord time:O(VE) space:O(
|
|
716
|
+
* BellmanFord time:O(VE) space:O(VO)
|
|
715
717
|
* one to rest pairs
|
|
716
718
|
* The Bellman-Ford algorithm is also used to find the shortest paths from a source node to all other nodes in a graph. Unlike Dijkstra's algorithm, it can handle edge weights that are negative. Its basic idea involves iterative relaxation of all edges for several rounds to gradually approximate the shortest paths. Due to its ability to handle negative-weight edges, the Bellman-Ford algorithm is more flexible in some scenarios.
|
|
717
719
|
* The `bellmanFord` function implements the Bellman-Ford algorithm to find the shortest path from a source vertex to
|
|
718
720
|
* all other vertices in a graph, and optionally detects negative cycles and generates the minimum path.
|
|
719
|
-
* @param {
|
|
721
|
+
* @param {VO | VertexKey} src - The `src` parameter is the source vertex from which the Bellman-Ford algorithm will
|
|
720
722
|
* start calculating the shortest paths. It can be either a vertex object or a vertex ID.
|
|
721
723
|
* @param {boolean} [scanNegativeCycle] - A boolean flag indicating whether to scan for negative cycles in the graph.
|
|
722
724
|
* @param {boolean} [getMin] - The `getMin` parameter is a boolean flag that determines whether the algorithm should
|
|
@@ -726,16 +728,16 @@ export abstract class AbstractGraph<
|
|
|
726
728
|
* vertex.
|
|
727
729
|
* @returns The function `bellmanFord` returns an object with the following properties:
|
|
728
730
|
*/
|
|
729
|
-
bellmanFord(src:
|
|
731
|
+
bellmanFord(src: VO | VertexKey, scanNegativeCycle?: boolean, getMin?: boolean, genPath?: boolean) {
|
|
730
732
|
if (getMin === undefined) getMin = false;
|
|
731
733
|
if (genPath === undefined) genPath = false;
|
|
732
734
|
|
|
733
735
|
const srcVertex = this._getVertex(src);
|
|
734
|
-
const paths:
|
|
735
|
-
const distMap: Map<
|
|
736
|
-
const preMap: Map<
|
|
736
|
+
const paths: VO[][] = [];
|
|
737
|
+
const distMap: Map<VO, number> = new Map();
|
|
738
|
+
const preMap: Map<VO, VO> = new Map(); // predecessor
|
|
737
739
|
let min = Infinity;
|
|
738
|
-
let minPath:
|
|
740
|
+
let minPath: VO[] = [];
|
|
739
741
|
// TODO
|
|
740
742
|
let hasNegativeCycle: boolean | undefined;
|
|
741
743
|
if (scanNegativeCycle) hasNegativeCycle = false;
|
|
@@ -770,7 +772,7 @@ export abstract class AbstractGraph<
|
|
|
770
772
|
}
|
|
771
773
|
}
|
|
772
774
|
|
|
773
|
-
let minDest:
|
|
775
|
+
let minDest: VO | null = null;
|
|
774
776
|
if (getMin) {
|
|
775
777
|
distMap.forEach((d, v) => {
|
|
776
778
|
if (v !== srcVertex) {
|
|
@@ -786,7 +788,7 @@ export abstract class AbstractGraph<
|
|
|
786
788
|
for (const vertex of vertices) {
|
|
787
789
|
const vertexOrKey = vertex[1];
|
|
788
790
|
if (vertexOrKey instanceof AbstractVertex) {
|
|
789
|
-
const path:
|
|
791
|
+
const path: VO[] = [vertexOrKey];
|
|
790
792
|
let parent = preMap.get(vertexOrKey);
|
|
791
793
|
while (parent !== undefined) {
|
|
792
794
|
path.push(parent);
|
|
@@ -815,34 +817,34 @@ export abstract class AbstractGraph<
|
|
|
815
817
|
}
|
|
816
818
|
|
|
817
819
|
/**
|
|
818
|
-
* Dijkstra algorithm time: O(logVE) space: O(
|
|
820
|
+
* Dijkstra algorithm time: O(logVE) space: O(VO + EO)
|
|
819
821
|
* /
|
|
820
822
|
|
|
821
823
|
/**
|
|
822
|
-
* Dijkstra algorithm time: O(logVE) space: O(
|
|
824
|
+
* Dijkstra algorithm time: O(logVE) space: O(VO + EO)
|
|
823
825
|
* Dijkstra's algorithm is used to find the shortest paths from a source node to all other nodes in a graph. Its basic idea is to repeatedly choose the node closest to the source node and update the distances of other nodes using this node as an intermediary. Dijkstra's algorithm requires that the edge weights in the graph are non-negative.
|
|
824
826
|
*/
|
|
825
827
|
|
|
826
828
|
/**
|
|
827
|
-
* BellmanFord time:O(VE) space:O(
|
|
829
|
+
* BellmanFord time:O(VE) space:O(VO)
|
|
828
830
|
* one to rest pairs
|
|
829
831
|
* The Bellman-Ford algorithm is also used to find the shortest paths from a source node to all other nodes in a graph. Unlike Dijkstra's algorithm, it can handle edge weights that are negative. Its basic idea involves iterative relaxation of all edges for several rounds to gradually approximate the shortest paths. Due to its ability to handle negative-weight edges, the Bellman-Ford algorithm is more flexible in some scenarios.
|
|
830
832
|
* The `bellmanFord` function implements the Bellman-Ford algorithm to find the shortest path from a source vertex to
|
|
831
833
|
*/
|
|
832
834
|
|
|
833
835
|
/**
|
|
834
|
-
* Floyd algorithm time: O(
|
|
836
|
+
* Floyd algorithm time: O(VO^3) space: O(VO^2), not support graph with negative weight cycle
|
|
835
837
|
* all pairs
|
|
836
838
|
* 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.
|
|
837
839
|
*/
|
|
838
840
|
|
|
839
841
|
/**
|
|
840
|
-
* Floyd algorithm time: O(
|
|
842
|
+
* Floyd algorithm time: O(VO^3) space: O(VO^2), not support graph with negative weight cycle
|
|
841
843
|
* all pairs
|
|
842
844
|
* /
|
|
843
845
|
|
|
844
846
|
/**
|
|
845
|
-
* Floyd algorithm time: O(
|
|
847
|
+
* Floyd algorithm time: O(VO^3) space: O(VO^2), not support graph with negative weight cycle
|
|
846
848
|
* all pairs
|
|
847
849
|
* 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.
|
|
848
850
|
* The function implements the Floyd-Warshall algorithm to find the shortest path between all pairs of vertices in a
|
|
@@ -852,12 +854,12 @@ export abstract class AbstractGraph<
|
|
|
852
854
|
* `predecessor` property is a 2D array of vertices (or `null`) representing the predecessor vertices in the shortest
|
|
853
855
|
* path between vertices in the
|
|
854
856
|
*/
|
|
855
|
-
floyd(): {costs: number[][]; predecessor: (
|
|
857
|
+
floyd(): {costs: number[][]; predecessor: (VO | null)[][]} {
|
|
856
858
|
const idAndVertices = [...this._vertices];
|
|
857
859
|
const n = idAndVertices.length;
|
|
858
860
|
|
|
859
861
|
const costs: number[][] = [];
|
|
860
|
-
const predecessor: (
|
|
862
|
+
const predecessor: (VO | null)[][] = [];
|
|
861
863
|
// successors
|
|
862
864
|
|
|
863
865
|
for (let i = 0; i < n; i++) {
|
|
@@ -927,8 +929,8 @@ export abstract class AbstractGraph<
|
|
|
927
929
|
if (needSCCs === undefined) needSCCs = defaultConfig;
|
|
928
930
|
if (needCycles === undefined) needCycles = defaultConfig;
|
|
929
931
|
|
|
930
|
-
const dfnMap: Map<
|
|
931
|
-
const lowMap: Map<
|
|
932
|
+
const dfnMap: Map<VO, number> = new Map();
|
|
933
|
+
const lowMap: Map<VO, number> = new Map();
|
|
932
934
|
const vertices = this._vertices;
|
|
933
935
|
vertices.forEach(v => {
|
|
934
936
|
dfnMap.set(v, -1);
|
|
@@ -937,10 +939,10 @@ export abstract class AbstractGraph<
|
|
|
937
939
|
|
|
938
940
|
const [root] = vertices.values();
|
|
939
941
|
|
|
940
|
-
const articulationPoints:
|
|
941
|
-
const bridges:
|
|
942
|
+
const articulationPoints: VO[] = [];
|
|
943
|
+
const bridges: EO[] = [];
|
|
942
944
|
let dfn = 0;
|
|
943
|
-
const dfs = (cur:
|
|
945
|
+
const dfs = (cur: VO, parent: VO | null) => {
|
|
944
946
|
dfn++;
|
|
945
947
|
dfnMap.set(cur, dfn);
|
|
946
948
|
lowMap.set(cur, dfn);
|
|
@@ -983,10 +985,10 @@ export abstract class AbstractGraph<
|
|
|
983
985
|
|
|
984
986
|
dfs(root, null);
|
|
985
987
|
|
|
986
|
-
let SCCs: Map<number,
|
|
988
|
+
let SCCs: Map<number, VO[]> = new Map();
|
|
987
989
|
|
|
988
990
|
const getSCCs = () => {
|
|
989
|
-
const SCCs: Map<number,
|
|
991
|
+
const SCCs: Map<number, VO[]> = new Map();
|
|
990
992
|
lowMap.forEach((low, vertex) => {
|
|
991
993
|
if (!SCCs.has(low)) {
|
|
992
994
|
SCCs.set(low, [vertex]);
|
|
@@ -1001,9 +1003,9 @@ export abstract class AbstractGraph<
|
|
|
1001
1003
|
SCCs = getSCCs();
|
|
1002
1004
|
}
|
|
1003
1005
|
|
|
1004
|
-
const cycles: Map<number,
|
|
1006
|
+
const cycles: Map<number, VO[]> = new Map();
|
|
1005
1007
|
if (needCycles) {
|
|
1006
|
-
let SCCs: Map<number,
|
|
1008
|
+
let SCCs: Map<number, VO[]> = new Map();
|
|
1007
1009
|
if (SCCs.size < 1) {
|
|
1008
1010
|
SCCs = getSCCs();
|
|
1009
1011
|
}
|
|
@@ -1018,9 +1020,9 @@ export abstract class AbstractGraph<
|
|
|
1018
1020
|
return {dfnMap, lowMap, bridges, articulationPoints, SCCs, cycles};
|
|
1019
1021
|
}
|
|
1020
1022
|
|
|
1021
|
-
protected abstract _addEdgeOnly(edge:
|
|
1023
|
+
protected abstract _addEdgeOnly(edge: EO): boolean;
|
|
1022
1024
|
|
|
1023
|
-
protected _addVertexOnly(newVertex:
|
|
1025
|
+
protected _addVertexOnly(newVertex: VO): boolean {
|
|
1024
1026
|
if (this.hasVertex(newVertex)) {
|
|
1025
1027
|
return false;
|
|
1026
1028
|
// throw (new Error('Duplicated vertex key is not allowed'));
|
|
@@ -1029,16 +1031,16 @@ export abstract class AbstractGraph<
|
|
|
1029
1031
|
return true;
|
|
1030
1032
|
}
|
|
1031
1033
|
|
|
1032
|
-
protected _getVertex(vertexOrKey: VertexKey |
|
|
1034
|
+
protected _getVertex(vertexOrKey: VertexKey | VO): VO | null {
|
|
1033
1035
|
const vertexKey = this._getVertexKey(vertexOrKey);
|
|
1034
1036
|
return this._vertices.get(vertexKey) || null;
|
|
1035
1037
|
}
|
|
1036
1038
|
|
|
1037
|
-
protected _getVertexKey(vertexOrKey:
|
|
1039
|
+
protected _getVertexKey(vertexOrKey: VO | VertexKey): VertexKey {
|
|
1038
1040
|
return vertexOrKey instanceof AbstractVertex ? vertexOrKey.key : vertexOrKey;
|
|
1039
1041
|
}
|
|
1040
1042
|
|
|
1041
|
-
protected _setVertices(value: Map<VertexKey,
|
|
1043
|
+
protected _setVertices(value: Map<VertexKey, VO>) {
|
|
1042
1044
|
this._vertices = value;
|
|
1043
1045
|
}
|
|
1044
1046
|
}
|