Update graph to use correct Queue methods

This commit is contained in:
mindfulminun committed 2023-04-04 00:41:37 -05:00
1 parent 4343355672
commit 9168c1620c
2 files changed
+69 -14

No files matched your search

+61 -6
View File
@@ -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)
}
}
+8 -8
View File
@@ -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)]
}