Update graph to use correct Queue methods
This commit is contained in:
2 files changed
+69
-14
No files matched your search
@@ -1,4 +1,4 @@
|
||||
import { Graph, Vertex, VertexType, EdgeType, Path, PathType } from "./graph.ts"
|
||||
import { Graph, Vertex, VertexType, Edge, EdgeType, Path, PathType } from "./graph.ts"
|
||||
import { Queue, Stack } from "../structures.ts"
|
||||
|
||||
/**
|
||||
@@ -43,7 +43,7 @@ export class GraphSolver<vData, eData> {
|
||||
const path = backPaths.get(v)!.copy()
|
||||
path.addEdge(E)
|
||||
backPaths.set(w, path)
|
||||
queue.enqueue(w)
|
||||
queue.push(w)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -102,8 +102,8 @@ export class GraphSolver<vData, eData> {
|
||||
const seenR = new Set<Vertex<vData, eData>>([right])
|
||||
|
||||
while (qL.length && qR.length) {
|
||||
const l = qL.dequeue()!
|
||||
const r = qR.dequeue()!
|
||||
const l = qL.pop()!
|
||||
const r = qR.pop()!
|
||||
|
||||
// The left side will traverse the graph normally,
|
||||
// following the direction of the arrows in the edges
|
||||
@@ -115,7 +115,7 @@ export class GraphSolver<vData, eData> {
|
||||
const path = backL.get(l)!.copy()
|
||||
path.addEdge(E)
|
||||
backL.set(w, path)
|
||||
qL.enqueue(w)
|
||||
qL.push(w)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -131,7 +131,7 @@ export class GraphSolver<vData, eData> {
|
||||
const path = backR.get(r)!.copy()
|
||||
path.addEdge(E)
|
||||
backR.set(w, path)
|
||||
qR.enqueue(w)
|
||||
qR.push(w)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -148,4 +148,59 @@ export class GraphSolver<vData, eData> {
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
/**
|
||||
* Sorts the edges by their weight ascending, then performs {@link kruskalPresorted | Kruskal's algorithm},
|
||||
* an algorithm for determining a minimum-spanning forest of a graph.
|
||||
*
|
||||
* Kruskal's greedy algorithm determines a minimum-spanning forest of a weighted, *undirected* graph.
|
||||
*
|
||||
* If you only wish to sort the edges, use {@link sortEdgesByWeight} instead.
|
||||
* @author MindfulMinun
|
||||
* @since 2023-03-30
|
||||
*/
|
||||
kruskalWithSort() {
|
||||
this.sortEdgesByWeight()
|
||||
return this.kruskalPresorted()
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs Kruskal's algorithm, assuming that the edges have been presorted.
|
||||
* This algorithm returns a set of the edges that span the graph.
|
||||
*
|
||||
* Kruskal's greedy algorithm determines a minimum-spanning forest of a weighted, *undirected* graph.
|
||||
*
|
||||
* This method assumes that the edges have been sorted by their weight ascending, allowing it to run in `O(m)` time.
|
||||
* If the edges have not been sorted, use {@link kruskalWithSort} instead.
|
||||
* @author MindfulMinun
|
||||
* @since 2023-03-30
|
||||
*/
|
||||
kruskalPresorted(edges?: Edge<vData, eData>[]) {
|
||||
const forest = new Set<Edge<vData, eData>>()
|
||||
/** Keeps track of the reachable vertices. Used to ensure that newly added edges do not create a cycle. */
|
||||
const reach = new WeakSet<Vertex<vData, eData>>()
|
||||
const ordered: Iterable<Edge<vData, eData>> = edges ?? this.G.edges.values()
|
||||
|
||||
for (const E of ordered) {
|
||||
if (forest.has(E)) continue
|
||||
if (reach.has(E.u) && reach.has(E.v)) continue
|
||||
forest.add(E)
|
||||
reach.add(E.u).add(E.v)
|
||||
}
|
||||
|
||||
return forest
|
||||
}
|
||||
|
||||
/**
|
||||
* Sorts edges by their weight ascending. Useful for speeding up algorithms such as Kruskal's.
|
||||
* This algorithm runs in `O(n log n)` time
|
||||
* @author MindfulMinun
|
||||
* @since 2023-03-30
|
||||
*/
|
||||
sortEdgesByWeight() {
|
||||
const edges = Array.from(this.G.edges.values())
|
||||
.sort((a, b) => this.G.weights(a) - this.G.weights(b))
|
||||
.map(e => [e.id, e] as const)
|
||||
this.G.edges = new Map(edges)
|
||||
}
|
||||
}
|
||||
@@ -25,9 +25,9 @@ interface EdgeOpts {
|
||||
*/
|
||||
export class Graph<vData, eData> {
|
||||
/** A map of the vertices in the graph. To add a new vertex, please use the {@link Graph.createVertex} method instead. */
|
||||
readonly vertices: Map<UUID, Vertex<vData, eData>>
|
||||
vertices: Map<UUID, Vertex<vData, eData>>
|
||||
/** A map of the edges in the graph. To add a new edge, please use the {@link Graph.createEdge} method instead. */
|
||||
readonly edges: Map<UUID, Edge<vData, eData>>
|
||||
edges: Map<UUID, Edge<vData, eData>>
|
||||
/**
|
||||
* Whether or not edges created in the graph are directed when the value is omitted.
|
||||
* Note that edges created with the `directed` option will use that value instead.
|
||||
@@ -149,17 +149,17 @@ export class Graph<vData, eData> {
|
||||
* @since 2022-07-26
|
||||
*/
|
||||
|
||||
export class Vertex<VertexData, EdgeData> {
|
||||
export class Vertex<vData, eData> {
|
||||
/* The graph this vertex belongs to */
|
||||
graph: Graph<VertexData, EdgeData>
|
||||
graph: Graph<vData, eData>
|
||||
/* The value stored in this vertex, up to you! */
|
||||
data: VertexData
|
||||
data: vData
|
||||
/* The unique identifier of this vertex */
|
||||
id: UUID
|
||||
/* The edges connected to this vertex */
|
||||
adjacentEdges: Set<Edge<VertexData, EdgeData>>
|
||||
adjacentEdges: Set<Edge<vData, eData>>
|
||||
|
||||
constructor(parentGraph: Graph<VertexData, EdgeData>, id: UUID, data: VertexData) {
|
||||
constructor(parentGraph: Graph<vData, eData>, id: UUID, data: vData) {
|
||||
this.graph = parentGraph
|
||||
this.data = data
|
||||
this.id = id
|
||||
@@ -168,7 +168,7 @@ export class Vertex<VertexData, EdgeData> {
|
||||
|
||||
delete() { this.graph.deleteVertex(this) }
|
||||
|
||||
toJSON(replacer: (this: Graph<VertexData, EdgeData>, data: VertexData) => unknown = data => data) {
|
||||
toJSON(replacer: (this: Graph<vData, eData>, data: vData) => unknown = data => data) {
|
||||
return [this.id, replacer.call(this.graph, this.data)]
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user