undirected-graph-typed 2.4.3 → 2.4.5
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 +225 -43
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/cjs-legacy/index.cjs +226 -42
- package/dist/cjs-legacy/index.cjs.map +1 -1
- package/dist/esm/index.mjs +225 -44
- package/dist/esm/index.mjs.map +1 -1
- package/dist/esm-legacy/index.mjs +226 -43
- package/dist/esm-legacy/index.mjs.map +1 -1
- package/dist/types/common/error.d.ts +23 -0
- package/dist/types/common/index.d.ts +1 -0
- package/dist/types/data-structures/base/iterable-element-base.d.ts +1 -1
- package/dist/types/data-structures/binary-tree/binary-tree.d.ts +15 -5
- package/dist/types/data-structures/binary-tree/bst.d.ts +1 -1
- package/dist/types/data-structures/binary-tree/red-black-tree.d.ts +7 -1
- package/dist/types/data-structures/graph/abstract-graph.d.ts +44 -0
- package/dist/types/data-structures/graph/directed-graph.d.ts +3 -2
- package/dist/types/data-structures/graph/undirected-graph.d.ts +16 -2
- package/dist/types/data-structures/hash/hash-map.d.ts +2 -2
- package/dist/types/data-structures/heap/heap.d.ts +3 -7
- package/dist/types/data-structures/queue/deque.d.ts +41 -1
- package/dist/types/types/data-structures/binary-tree/avl-tree.d.ts +1 -1
- package/dist/types/types/data-structures/binary-tree/red-black-tree.d.ts +1 -1
- package/dist/types/types/data-structures/linked-list/doubly-linked-list.d.ts +1 -1
- package/dist/types/types/data-structures/linked-list/singly-linked-list.d.ts +1 -1
- package/dist/types/types/data-structures/priority-queue/priority-queue.d.ts +1 -1
- package/dist/types/types/data-structures/queue/deque.d.ts +6 -0
- package/dist/types/types/data-structures/stack/stack.d.ts +1 -1
- package/dist/umd/undirected-graph-typed.js +224 -40
- package/dist/umd/undirected-graph-typed.js.map +1 -1
- package/dist/umd/undirected-graph-typed.min.js +3 -1
- package/dist/umd/undirected-graph-typed.min.js.map +1 -1
- package/package.json +2 -2
- package/src/common/error.ts +60 -0
- package/src/common/index.ts +2 -0
- package/src/data-structures/base/iterable-element-base.ts +5 -4
- package/src/data-structures/binary-tree/binary-indexed-tree.ts +6 -5
- package/src/data-structures/binary-tree/binary-tree.ts +121 -49
- package/src/data-structures/binary-tree/bst.ts +12 -4
- package/src/data-structures/binary-tree/red-black-tree.ts +20 -0
- package/src/data-structures/binary-tree/tree-map.ts +8 -7
- package/src/data-structures/binary-tree/tree-multi-map.ts +4 -4
- package/src/data-structures/binary-tree/tree-multi-set.ts +10 -9
- package/src/data-structures/binary-tree/tree-set.ts +7 -6
- package/src/data-structures/graph/abstract-graph.ts +124 -19
- package/src/data-structures/graph/directed-graph.ts +8 -4
- package/src/data-structures/graph/map-graph.ts +1 -1
- package/src/data-structures/graph/undirected-graph.ts +99 -4
- package/src/data-structures/hash/hash-map.ts +19 -6
- package/src/data-structures/heap/heap.ts +21 -17
- package/src/data-structures/heap/max-heap.ts +2 -3
- package/src/data-structures/linked-list/doubly-linked-list.ts +4 -4
- package/src/data-structures/linked-list/singly-linked-list.ts +15 -9
- package/src/data-structures/matrix/matrix.ts +9 -10
- package/src/data-structures/priority-queue/max-priority-queue.ts +2 -3
- package/src/data-structures/queue/deque.ts +72 -4
- package/src/data-structures/stack/stack.ts +1 -1
- package/src/data-structures/trie/trie.ts +12 -6
- package/src/types/data-structures/binary-tree/avl-tree.ts +1 -1
- package/src/types/data-structures/binary-tree/red-black-tree.ts +1 -1
- package/src/types/data-structures/linked-list/doubly-linked-list.ts +1 -1
- package/src/types/data-structures/linked-list/singly-linked-list.ts +1 -1
- package/src/types/data-structures/priority-queue/priority-queue.ts +1 -1
- package/src/types/data-structures/queue/deque.ts +7 -0
- package/src/types/data-structures/stack/stack.ts +1 -1
- package/src/utils/utils.ts +4 -2
package/dist/cjs/index.cjs
CHANGED
|
@@ -24,6 +24,55 @@ var arrayRemove = /* @__PURE__ */ __name(function(array, predicate) {
|
|
|
24
24
|
return result;
|
|
25
25
|
}, "arrayRemove");
|
|
26
26
|
|
|
27
|
+
// src/common/error.ts
|
|
28
|
+
var ERR = {
|
|
29
|
+
// Range / index
|
|
30
|
+
indexOutOfRange: /* @__PURE__ */ __name((index, min, max, ctx) => `${ctx ? ctx + ": " : ""}Index ${index} is out of range [${min}, ${max}].`, "indexOutOfRange"),
|
|
31
|
+
invalidIndex: /* @__PURE__ */ __name((ctx) => `${ctx ? ctx + ": " : ""}Index must be an integer.`, "invalidIndex"),
|
|
32
|
+
// Type / argument
|
|
33
|
+
invalidArgument: /* @__PURE__ */ __name((reason, ctx) => `${ctx ? ctx + ": " : ""}${reason}`, "invalidArgument"),
|
|
34
|
+
comparatorRequired: /* @__PURE__ */ __name((ctx) => `${ctx ? ctx + ": " : ""}Comparator is required for non-number/non-string/non-Date keys.`, "comparatorRequired"),
|
|
35
|
+
invalidKey: /* @__PURE__ */ __name((reason, ctx) => `${ctx ? ctx + ": " : ""}${reason}`, "invalidKey"),
|
|
36
|
+
notAFunction: /* @__PURE__ */ __name((name, ctx) => `${ctx ? ctx + ": " : ""}${name} must be a function.`, "notAFunction"),
|
|
37
|
+
invalidEntry: /* @__PURE__ */ __name((ctx) => `${ctx ? ctx + ": " : ""}Each entry must be a [key, value] tuple.`, "invalidEntry"),
|
|
38
|
+
invalidNaN: /* @__PURE__ */ __name((ctx) => `${ctx ? ctx + ": " : ""}NaN is not a valid key.`, "invalidNaN"),
|
|
39
|
+
invalidDate: /* @__PURE__ */ __name((ctx) => `${ctx ? ctx + ": " : ""}Invalid Date key.`, "invalidDate"),
|
|
40
|
+
reduceEmpty: /* @__PURE__ */ __name((ctx) => `${ctx ? ctx + ": " : ""}Reduce of empty structure with no initial value.`, "reduceEmpty"),
|
|
41
|
+
callbackReturnType: /* @__PURE__ */ __name((expected, got, ctx) => `${ctx ? ctx + ": " : ""}Callback must return ${expected}; got ${got}.`, "callbackReturnType"),
|
|
42
|
+
// State / operation
|
|
43
|
+
invalidOperation: /* @__PURE__ */ __name((reason, ctx) => `${ctx ? ctx + ": " : ""}${reason}`, "invalidOperation"),
|
|
44
|
+
// Matrix
|
|
45
|
+
matrixDimensionMismatch: /* @__PURE__ */ __name((op) => `Matrix: Dimensions must be compatible for ${op}.`, "matrixDimensionMismatch"),
|
|
46
|
+
matrixSingular: /* @__PURE__ */ __name(() => "Matrix: Singular matrix, inverse does not exist.", "matrixSingular"),
|
|
47
|
+
matrixNotSquare: /* @__PURE__ */ __name(() => "Matrix: Must be square for inversion.", "matrixNotSquare"),
|
|
48
|
+
matrixNotRectangular: /* @__PURE__ */ __name(() => "Matrix: Must be rectangular for transposition.", "matrixNotRectangular"),
|
|
49
|
+
matrixRowMismatch: /* @__PURE__ */ __name((expected, got) => `Matrix: Expected row length ${expected}, but got ${got}.`, "matrixRowMismatch")
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
// src/common/index.ts
|
|
53
|
+
var DFSOperation = /* @__PURE__ */ ((DFSOperation2) => {
|
|
54
|
+
DFSOperation2[DFSOperation2["VISIT"] = 0] = "VISIT";
|
|
55
|
+
DFSOperation2[DFSOperation2["PROCESS"] = 1] = "PROCESS";
|
|
56
|
+
return DFSOperation2;
|
|
57
|
+
})(DFSOperation || {});
|
|
58
|
+
var Range = class {
|
|
59
|
+
constructor(low, high, includeLow = true, includeHigh = true) {
|
|
60
|
+
this.low = low;
|
|
61
|
+
this.high = high;
|
|
62
|
+
this.includeLow = includeLow;
|
|
63
|
+
this.includeHigh = includeHigh;
|
|
64
|
+
}
|
|
65
|
+
static {
|
|
66
|
+
__name(this, "Range");
|
|
67
|
+
}
|
|
68
|
+
// Determine whether a key is within the range
|
|
69
|
+
isInRange(key, comparator) {
|
|
70
|
+
const lowCheck = this.includeLow ? comparator(key, this.low) >= 0 : comparator(key, this.low) > 0;
|
|
71
|
+
const highCheck = this.includeHigh ? comparator(key, this.high) <= 0 : comparator(key, this.high) < 0;
|
|
72
|
+
return lowCheck && highCheck;
|
|
73
|
+
}
|
|
74
|
+
};
|
|
75
|
+
|
|
27
76
|
// src/data-structures/base/iterable-entry-base.ts
|
|
28
77
|
var IterableEntryBase = class {
|
|
29
78
|
static {
|
|
@@ -224,7 +273,7 @@ var IterableElementBase = class {
|
|
|
224
273
|
if (options) {
|
|
225
274
|
const { toElementFn } = options;
|
|
226
275
|
if (typeof toElementFn === "function") this._toElementFn = toElementFn;
|
|
227
|
-
else if (toElementFn) throw new TypeError("toElementFn
|
|
276
|
+
else if (toElementFn) throw new TypeError(ERR.notAFunction("toElementFn"));
|
|
228
277
|
}
|
|
229
278
|
}
|
|
230
279
|
/**
|
|
@@ -387,7 +436,7 @@ var IterableElementBase = class {
|
|
|
387
436
|
acc = initialValue;
|
|
388
437
|
} else {
|
|
389
438
|
const first = iter.next();
|
|
390
|
-
if (first.done) throw new TypeError(
|
|
439
|
+
if (first.done) throw new TypeError(ERR.reduceEmpty());
|
|
391
440
|
acc = first.value;
|
|
392
441
|
index = 1;
|
|
393
442
|
}
|
|
@@ -747,7 +796,7 @@ var Heap = class _Heap extends IterableElementBase {
|
|
|
747
796
|
*/
|
|
748
797
|
map(callback, options, thisArg) {
|
|
749
798
|
const { comparator, toElementFn, ...rest } = options ?? {};
|
|
750
|
-
if (!comparator) throw new TypeError("Heap.map
|
|
799
|
+
if (!comparator) throw new TypeError(ERR.comparatorRequired("Heap.map"));
|
|
751
800
|
const out = this._createLike([], { ...rest, comparator, toElementFn });
|
|
752
801
|
let i = 0;
|
|
753
802
|
for (const x of this) {
|
|
@@ -774,18 +823,13 @@ var Heap = class _Heap extends IterableElementBase {
|
|
|
774
823
|
}
|
|
775
824
|
_DEFAULT_COMPARATOR = /* @__PURE__ */ __name((a, b) => {
|
|
776
825
|
if (typeof a === "object" || typeof b === "object") {
|
|
777
|
-
throw TypeError(
|
|
826
|
+
throw new TypeError(ERR.comparatorRequired("Heap"));
|
|
778
827
|
}
|
|
779
828
|
if (a > b) return 1;
|
|
780
829
|
if (a < b) return -1;
|
|
781
830
|
return 0;
|
|
782
831
|
}, "_DEFAULT_COMPARATOR");
|
|
783
832
|
_comparator = this._DEFAULT_COMPARATOR;
|
|
784
|
-
/**
|
|
785
|
-
* Get the comparator used to order elements.
|
|
786
|
-
* @remarks Time O(1), Space O(1)
|
|
787
|
-
* @returns Comparator function.
|
|
788
|
-
*/
|
|
789
833
|
/**
|
|
790
834
|
* Get the comparator used to order elements.
|
|
791
835
|
* @remarks Time O(1), Space O(1)
|
|
@@ -834,8 +878,7 @@ var Heap = class _Heap extends IterableElementBase {
|
|
|
834
878
|
*/
|
|
835
879
|
_createInstance(options) {
|
|
836
880
|
const Ctor = this.constructor;
|
|
837
|
-
|
|
838
|
-
return next;
|
|
881
|
+
return new Ctor([], { comparator: this.comparator, toElementFn: this.toElementFn, ...options ?? {} });
|
|
839
882
|
}
|
|
840
883
|
/**
|
|
841
884
|
* (Protected) Create a like-kind instance seeded by elements.
|
|
@@ -1567,7 +1610,7 @@ var AbstractGraph = class extends IterableEntryBase {
|
|
|
1567
1610
|
const newEdge = this.createEdge(srcOrEdge, dest, weight, value);
|
|
1568
1611
|
return this._addEdge(newEdge);
|
|
1569
1612
|
} else {
|
|
1570
|
-
throw new
|
|
1613
|
+
throw new TypeError(ERR.invalidArgument("dest must be a Vertex or vertex key when srcOrEdge is an Edge.", "Graph"));
|
|
1571
1614
|
}
|
|
1572
1615
|
}
|
|
1573
1616
|
}
|
|
@@ -2172,8 +2215,8 @@ var AbstractGraph = class extends IterableEntryBase {
|
|
|
2172
2215
|
const Ctor = this.constructor;
|
|
2173
2216
|
const instance = new Ctor();
|
|
2174
2217
|
const graph = _options?.graph;
|
|
2175
|
-
if (graph) instance
|
|
2176
|
-
else instance
|
|
2218
|
+
if (graph) instance["_options"] = { ...instance["_options"], ...graph };
|
|
2219
|
+
else instance["_options"] = { ...instance["_options"], ...this._options };
|
|
2177
2220
|
return instance;
|
|
2178
2221
|
}
|
|
2179
2222
|
/**
|
|
@@ -2206,12 +2249,10 @@ var AbstractGraph = class extends IterableEntryBase {
|
|
|
2206
2249
|
const [va, vb] = ends;
|
|
2207
2250
|
const ka = va.key;
|
|
2208
2251
|
const kb = vb.key;
|
|
2209
|
-
const hasA = g.hasVertex ? g.hasVertex(ka) : false;
|
|
2210
|
-
const hasB = g.hasVertex ? g.hasVertex(kb) : false;
|
|
2252
|
+
const hasA = typeof g.hasVertex === "function" ? g.hasVertex(ka) : false;
|
|
2253
|
+
const hasB = typeof g.hasVertex === "function" ? g.hasVertex(kb) : false;
|
|
2211
2254
|
if (hasA && hasB) {
|
|
2212
|
-
const
|
|
2213
|
-
const val = e.value;
|
|
2214
|
-
const newEdge = g.createEdge(ka, kb, w, val);
|
|
2255
|
+
const newEdge = g.createEdge(ka, kb, e.weight, e.value);
|
|
2215
2256
|
g._addEdge(newEdge);
|
|
2216
2257
|
}
|
|
2217
2258
|
}
|
|
@@ -2249,6 +2290,92 @@ var AbstractGraph = class extends IterableEntryBase {
|
|
|
2249
2290
|
_getVertexKey(vertexOrKey) {
|
|
2250
2291
|
return vertexOrKey instanceof AbstractVertex ? vertexOrKey.key : vertexOrKey;
|
|
2251
2292
|
}
|
|
2293
|
+
/**
|
|
2294
|
+
* The edge connector string used in visual output.
|
|
2295
|
+
* Override in subclasses (e.g., '--' for undirected, '->' for directed).
|
|
2296
|
+
*/
|
|
2297
|
+
get _edgeConnector() {
|
|
2298
|
+
return "--";
|
|
2299
|
+
}
|
|
2300
|
+
/**
|
|
2301
|
+
* Generate a text-based visual representation of the graph.
|
|
2302
|
+
*
|
|
2303
|
+
* **Adjacency list format:**
|
|
2304
|
+
* ```
|
|
2305
|
+
* Graph (5 vertices, 6 edges):
|
|
2306
|
+
* A -> B (1), C (2)
|
|
2307
|
+
* B -> D (3)
|
|
2308
|
+
* C -> (no outgoing edges)
|
|
2309
|
+
* D -> A (1)
|
|
2310
|
+
* E (isolated)
|
|
2311
|
+
* ```
|
|
2312
|
+
*
|
|
2313
|
+
* @param options - Optional display settings.
|
|
2314
|
+
* @param options.showWeight - Whether to show edge weights (default: true).
|
|
2315
|
+
* @returns The visual string.
|
|
2316
|
+
*/
|
|
2317
|
+
toVisual(options) {
|
|
2318
|
+
const showWeight = options?.showWeight ?? true;
|
|
2319
|
+
const vertices = [...this._vertexMap.values()];
|
|
2320
|
+
const vertexCount = vertices.length;
|
|
2321
|
+
const edgeCount = this.edgeSet().length;
|
|
2322
|
+
const lines = [`Graph (${vertexCount} vertices, ${edgeCount} edges):`];
|
|
2323
|
+
for (const vertex of vertices) {
|
|
2324
|
+
const neighbors = this.getNeighbors(vertex);
|
|
2325
|
+
if (neighbors.length === 0) {
|
|
2326
|
+
lines.push(` ${vertex.key} (isolated)`);
|
|
2327
|
+
} else {
|
|
2328
|
+
const edgeStrs = neighbors.map((neighbor) => {
|
|
2329
|
+
const edge = this.getEdge(vertex, neighbor);
|
|
2330
|
+
if (edge && showWeight && edge.weight !== void 0 && edge.weight !== 1) {
|
|
2331
|
+
return `${neighbor.key} (${edge.weight})`;
|
|
2332
|
+
}
|
|
2333
|
+
return `${neighbor.key}`;
|
|
2334
|
+
});
|
|
2335
|
+
lines.push(` ${vertex.key} ${this._edgeConnector} ${edgeStrs.join(", ")}`);
|
|
2336
|
+
}
|
|
2337
|
+
}
|
|
2338
|
+
return lines.join("\n");
|
|
2339
|
+
}
|
|
2340
|
+
/**
|
|
2341
|
+
* Generate DOT language representation for Graphviz.
|
|
2342
|
+
*
|
|
2343
|
+
* @param options - Optional display settings.
|
|
2344
|
+
* @param options.name - Graph name (default: 'G').
|
|
2345
|
+
* @param options.showWeight - Whether to label edges with weight (default: true).
|
|
2346
|
+
* @returns DOT format string.
|
|
2347
|
+
*/
|
|
2348
|
+
toDot(options) {
|
|
2349
|
+
const name = options?.name ?? "G";
|
|
2350
|
+
const showWeight = options?.showWeight ?? true;
|
|
2351
|
+
const isDirected = this._edgeConnector === "->";
|
|
2352
|
+
const graphType = isDirected ? "digraph" : "graph";
|
|
2353
|
+
const edgeOp = isDirected ? "->" : "--";
|
|
2354
|
+
const lines = [`${graphType} ${name} {`];
|
|
2355
|
+
for (const vertex of this._vertexMap.values()) {
|
|
2356
|
+
lines.push(` "${vertex.key}";`);
|
|
2357
|
+
}
|
|
2358
|
+
const visited = /* @__PURE__ */ new Set();
|
|
2359
|
+
for (const vertex of this._vertexMap.values()) {
|
|
2360
|
+
for (const neighbor of this.getNeighbors(vertex)) {
|
|
2361
|
+
const edgeId = isDirected ? `${vertex.key}->${neighbor.key}` : [vertex.key, neighbor.key].sort().join("--");
|
|
2362
|
+
if (visited.has(edgeId)) continue;
|
|
2363
|
+
visited.add(edgeId);
|
|
2364
|
+
const edge = this.getEdge(vertex, neighbor);
|
|
2365
|
+
const label = edge && showWeight && edge.weight !== void 0 && edge.weight !== 1 ? ` [label="${edge.weight}"]` : "";
|
|
2366
|
+
lines.push(` "${vertex.key}" ${edgeOp} "${neighbor.key}"${label};`);
|
|
2367
|
+
}
|
|
2368
|
+
}
|
|
2369
|
+
lines.push("}");
|
|
2370
|
+
return lines.join("\n");
|
|
2371
|
+
}
|
|
2372
|
+
/**
|
|
2373
|
+
* Print the graph to console.
|
|
2374
|
+
* @param options - Display settings passed to `toVisual`.
|
|
2375
|
+
*/
|
|
2376
|
+
print(options) {
|
|
2377
|
+
console.log(this.toVisual(options));
|
|
2378
|
+
}
|
|
2252
2379
|
};
|
|
2253
2380
|
|
|
2254
2381
|
// src/data-structures/graph/undirected-graph.ts
|
|
@@ -2585,6 +2712,84 @@ var UndirectedGraph = class _UndirectedGraph extends AbstractGraph {
|
|
|
2585
2712
|
cutVertices
|
|
2586
2713
|
};
|
|
2587
2714
|
}
|
|
2715
|
+
/**
|
|
2716
|
+
* Find biconnected components using edge-stack Tarjan variant.
|
|
2717
|
+
* A biconnected component is a maximal biconnected subgraph.
|
|
2718
|
+
* @returns Array of edge arrays, each representing a biconnected component.
|
|
2719
|
+
* @remarks Time O(V + E), Space O(V + E)
|
|
2720
|
+
*/
|
|
2721
|
+
getBiconnectedComponents() {
|
|
2722
|
+
const dfn = /* @__PURE__ */ new Map();
|
|
2723
|
+
const low = /* @__PURE__ */ new Map();
|
|
2724
|
+
const edgeStack = [];
|
|
2725
|
+
const components = [];
|
|
2726
|
+
let time = 0;
|
|
2727
|
+
const dfs = /* @__PURE__ */ __name((vertex, parent) => {
|
|
2728
|
+
dfn.set(vertex, time);
|
|
2729
|
+
low.set(vertex, time);
|
|
2730
|
+
time++;
|
|
2731
|
+
const neighbors = this.getNeighbors(vertex);
|
|
2732
|
+
let childCount = 0;
|
|
2733
|
+
for (const neighbor of neighbors) {
|
|
2734
|
+
const edge = this.getEdge(vertex, neighbor);
|
|
2735
|
+
if (!edge) continue;
|
|
2736
|
+
if (!dfn.has(neighbor)) {
|
|
2737
|
+
childCount++;
|
|
2738
|
+
edgeStack.push(edge);
|
|
2739
|
+
dfs(neighbor, vertex);
|
|
2740
|
+
low.set(vertex, Math.min(low.get(vertex), low.get(neighbor)));
|
|
2741
|
+
if (parent === void 0 && childCount > 1 || parent !== void 0 && low.get(neighbor) >= dfn.get(vertex)) {
|
|
2742
|
+
const component = [];
|
|
2743
|
+
let e;
|
|
2744
|
+
do {
|
|
2745
|
+
e = edgeStack.pop();
|
|
2746
|
+
if (e) component.push(e);
|
|
2747
|
+
} while (e && e !== edge);
|
|
2748
|
+
if (component.length > 0) components.push(component);
|
|
2749
|
+
}
|
|
2750
|
+
} else if (neighbor !== parent && dfn.get(neighbor) < dfn.get(vertex)) {
|
|
2751
|
+
edgeStack.push(edge);
|
|
2752
|
+
low.set(vertex, Math.min(low.get(vertex), dfn.get(neighbor)));
|
|
2753
|
+
}
|
|
2754
|
+
}
|
|
2755
|
+
}, "dfs");
|
|
2756
|
+
for (const vertex of this.vertexMap.values()) {
|
|
2757
|
+
if (!dfn.has(vertex)) {
|
|
2758
|
+
dfs(vertex, void 0);
|
|
2759
|
+
if (edgeStack.length > 0) {
|
|
2760
|
+
components.push([...edgeStack]);
|
|
2761
|
+
edgeStack.length = 0;
|
|
2762
|
+
}
|
|
2763
|
+
}
|
|
2764
|
+
}
|
|
2765
|
+
return components;
|
|
2766
|
+
}
|
|
2767
|
+
/**
|
|
2768
|
+
* Detect whether the graph contains a cycle.
|
|
2769
|
+
* Uses DFS with parent tracking.
|
|
2770
|
+
* @returns `true` if a cycle exists, `false` otherwise.
|
|
2771
|
+
* @remarks Time O(V + E), Space O(V)
|
|
2772
|
+
*/
|
|
2773
|
+
hasCycle() {
|
|
2774
|
+
const visited = /* @__PURE__ */ new Set();
|
|
2775
|
+
const dfs = /* @__PURE__ */ __name((vertex, parent) => {
|
|
2776
|
+
visited.add(vertex);
|
|
2777
|
+
for (const neighbor of this.getNeighbors(vertex)) {
|
|
2778
|
+
if (!visited.has(neighbor)) {
|
|
2779
|
+
if (dfs(neighbor, vertex)) return true;
|
|
2780
|
+
} else if (neighbor !== parent) {
|
|
2781
|
+
return true;
|
|
2782
|
+
}
|
|
2783
|
+
}
|
|
2784
|
+
return false;
|
|
2785
|
+
}, "dfs");
|
|
2786
|
+
for (const vertex of this.vertexMap.values()) {
|
|
2787
|
+
if (!visited.has(vertex)) {
|
|
2788
|
+
if (dfs(vertex, void 0)) return true;
|
|
2789
|
+
}
|
|
2790
|
+
}
|
|
2791
|
+
return false;
|
|
2792
|
+
}
|
|
2588
2793
|
/**
|
|
2589
2794
|
* Get bridges discovered by `tarjan()`.
|
|
2590
2795
|
* @returns Array of edges that are bridges.
|
|
@@ -2639,30 +2844,6 @@ var UndirectedGraph = class _UndirectedGraph extends AbstractGraph {
|
|
|
2639
2844
|
return true;
|
|
2640
2845
|
}
|
|
2641
2846
|
};
|
|
2642
|
-
|
|
2643
|
-
// src/common/index.ts
|
|
2644
|
-
var DFSOperation = /* @__PURE__ */ ((DFSOperation2) => {
|
|
2645
|
-
DFSOperation2[DFSOperation2["VISIT"] = 0] = "VISIT";
|
|
2646
|
-
DFSOperation2[DFSOperation2["PROCESS"] = 1] = "PROCESS";
|
|
2647
|
-
return DFSOperation2;
|
|
2648
|
-
})(DFSOperation || {});
|
|
2649
|
-
var Range = class {
|
|
2650
|
-
constructor(low, high, includeLow = true, includeHigh = true) {
|
|
2651
|
-
this.low = low;
|
|
2652
|
-
this.high = high;
|
|
2653
|
-
this.includeLow = includeLow;
|
|
2654
|
-
this.includeHigh = includeHigh;
|
|
2655
|
-
}
|
|
2656
|
-
static {
|
|
2657
|
-
__name(this, "Range");
|
|
2658
|
-
}
|
|
2659
|
-
// Determine whether a key is within the range
|
|
2660
|
-
isInRange(key, comparator) {
|
|
2661
|
-
const lowCheck = this.includeLow ? comparator(key, this.low) >= 0 : comparator(key, this.low) > 0;
|
|
2662
|
-
const highCheck = this.includeHigh ? comparator(key, this.high) <= 0 : comparator(key, this.high) < 0;
|
|
2663
|
-
return lowCheck && highCheck;
|
|
2664
|
-
}
|
|
2665
|
-
};
|
|
2666
2847
|
/**
|
|
2667
2848
|
* data-structure-typed
|
|
2668
2849
|
*
|
|
@@ -2672,6 +2853,7 @@ var Range = class {
|
|
|
2672
2853
|
*/
|
|
2673
2854
|
|
|
2674
2855
|
exports.DFSOperation = DFSOperation;
|
|
2856
|
+
exports.ERR = ERR;
|
|
2675
2857
|
exports.Range = Range;
|
|
2676
2858
|
exports.UndirectedEdge = UndirectedEdge;
|
|
2677
2859
|
exports.UndirectedGraph = UndirectedGraph;
|