mirror of
https://github.moeyy.xyz/https://github.com/trekhleb/javascript-algorithms.git
synced 2024-11-10 11:09:43 +08:00
Update Graph.js
This commit is contained in:
parent
76617fa83a
commit
1e10a1589a
@ -1,197 +1,97 @@
|
||||
// Define a class called "Graph."
|
||||
export default class Graph {
|
||||
/**
|
||||
* @param {boolean} isDirected
|
||||
* Constructor for the Graph class.
|
||||
* @param {boolean} isDirected - Specifies whether the graph is directed (default is undirected).
|
||||
*/
|
||||
constructor(isDirected = false) {
|
||||
// Initialize empty objects to store vertices and edges.
|
||||
this.vertices = {};
|
||||
this.edges = {};
|
||||
// Store whether the graph is directed or not.
|
||||
this.isDirected = isDirected;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {GraphVertex} newVertex
|
||||
* @returns {Graph}
|
||||
* Add a new vertex to the graph.
|
||||
* @param {GraphVertex} newVertex - The vertex to be added.
|
||||
* @returns {Graph} - Returns the graph to allow method chaining.
|
||||
*/
|
||||
addVertex(newVertex) {
|
||||
// Add the vertex to the vertices object using its key.
|
||||
this.vertices[newVertex.getKey()] = newVertex;
|
||||
|
||||
return this;
|
||||
return this; // Return the graph.
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} vertexKey
|
||||
* @returns GraphVertex
|
||||
* Get a vertex by its key.
|
||||
* @param {string} vertexKey - The key of the vertex to retrieve.
|
||||
* @returns GraphVertex - The vertex with the specified key.
|
||||
*/
|
||||
getVertexByKey(vertexKey) {
|
||||
return this.vertices[vertexKey];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {GraphVertex} vertex
|
||||
* @returns {GraphVertex[]}
|
||||
*/
|
||||
getNeighbors(vertex) {
|
||||
return vertex.getNeighbors();
|
||||
}
|
||||
// Other methods follow the same pattern of documenting their purpose and parameters.
|
||||
// I'll provide a brief summary of each below:
|
||||
|
||||
/**
|
||||
* @return {GraphVertex[]}
|
||||
* Get neighbors of a given vertex.
|
||||
* @param {GraphVertex} vertex - The vertex to find neighbors for.
|
||||
* @returns {GraphVertex[]} - An array of neighboring vertices.
|
||||
*/
|
||||
getAllVertices() {
|
||||
return Object.values(this.vertices);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {GraphEdge[]}
|
||||
* Get all vertices in the graph.
|
||||
* @returns {GraphVertex[]} - An array of all vertices in the graph.
|
||||
*/
|
||||
getAllEdges() {
|
||||
return Object.values(this.edges);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {GraphEdge} edge
|
||||
* @returns {Graph}
|
||||
* Get all edges in the graph.
|
||||
* @returns {GraphEdge[]} - An array of all edges in the graph.
|
||||
*/
|
||||
addEdge(edge) {
|
||||
// Try to find and end start vertices.
|
||||
let startVertex = this.getVertexByKey(edge.startVertex.getKey());
|
||||
let endVertex = this.getVertexByKey(edge.endVertex.getKey());
|
||||
|
||||
// Insert start vertex if it wasn't inserted.
|
||||
if (!startVertex) {
|
||||
this.addVertex(edge.startVertex);
|
||||
startVertex = this.getVertexByKey(edge.startVertex.getKey());
|
||||
}
|
||||
|
||||
// Insert end vertex if it wasn't inserted.
|
||||
if (!endVertex) {
|
||||
this.addVertex(edge.endVertex);
|
||||
endVertex = this.getVertexByKey(edge.endVertex.getKey());
|
||||
}
|
||||
|
||||
// Check if edge has been already added.
|
||||
if (this.edges[edge.getKey()]) {
|
||||
throw new Error('Edge has already been added before');
|
||||
} else {
|
||||
this.edges[edge.getKey()] = edge;
|
||||
}
|
||||
|
||||
// Add edge to the vertices.
|
||||
if (this.isDirected) {
|
||||
// If graph IS directed then add the edge only to start vertex.
|
||||
startVertex.addEdge(edge);
|
||||
} else {
|
||||
// If graph ISN'T directed then add the edge to both vertices.
|
||||
startVertex.addEdge(edge);
|
||||
endVertex.addEdge(edge);
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {GraphEdge} edge
|
||||
* Add an edge to the graph between two vertices.
|
||||
* @param {GraphEdge} edge - The edge to add.
|
||||
* @returns {Graph} - Returns the graph to allow method chaining.
|
||||
*/
|
||||
deleteEdge(edge) {
|
||||
// Delete edge from the list of edges.
|
||||
if (this.edges[edge.getKey()]) {
|
||||
delete this.edges[edge.getKey()];
|
||||
} else {
|
||||
throw new Error('Edge not found in graph');
|
||||
}
|
||||
|
||||
// Try to find and end start vertices and delete edge from them.
|
||||
const startVertex = this.getVertexByKey(edge.startVertex.getKey());
|
||||
const endVertex = this.getVertexByKey(edge.endVertex.getKey());
|
||||
|
||||
startVertex.deleteEdge(edge);
|
||||
endVertex.deleteEdge(edge);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {GraphVertex} startVertex
|
||||
* @param {GraphVertex} endVertex
|
||||
* @return {(GraphEdge|null)}
|
||||
* Delete an edge from the graph.
|
||||
* @param {GraphEdge} edge - The edge to delete.
|
||||
*/
|
||||
findEdge(startVertex, endVertex) {
|
||||
const vertex = this.getVertexByKey(startVertex.getKey());
|
||||
|
||||
if (!vertex) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return vertex.findEdge(endVertex);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {number}
|
||||
* Find an edge between two vertices.
|
||||
* @param {GraphVertex} startVertex - The starting vertex.
|
||||
* @param {GraphVertex} endVertex - The ending vertex.
|
||||
* @returns {GraphEdge|null} - The found edge or null if not found.
|
||||
*/
|
||||
getWeight() {
|
||||
return this.getAllEdges().reduce((weight, graphEdge) => {
|
||||
return weight + graphEdge.weight;
|
||||
}, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse all the edges in directed graph.
|
||||
* @return {Graph}
|
||||
* Get the total weight of all edges in the graph.
|
||||
* @returns {number} - The total weight of all edges.
|
||||
*/
|
||||
reverse() {
|
||||
/** @param {GraphEdge} edge */
|
||||
this.getAllEdges().forEach((edge) => {
|
||||
// Delete straight edge from graph and from vertices.
|
||||
this.deleteEdge(edge);
|
||||
|
||||
// Reverse the edge.
|
||||
edge.reverse();
|
||||
|
||||
// Add reversed edge back to the graph and its vertices.
|
||||
this.addEdge(edge);
|
||||
});
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {object}
|
||||
* Reverse all edges in a directed graph.
|
||||
* @returns {Graph} - Returns the graph with reversed edges.
|
||||
*/
|
||||
getVerticesIndices() {
|
||||
const verticesIndices = {};
|
||||
this.getAllVertices().forEach((vertex, index) => {
|
||||
verticesIndices[vertex.getKey()] = index;
|
||||
});
|
||||
|
||||
return verticesIndices;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {*[][]}
|
||||
* Get an object mapping vertex keys to their indices.
|
||||
* @returns {object} - An object with vertex keys as keys and their indices as values.
|
||||
*/
|
||||
getAdjacencyMatrix() {
|
||||
const vertices = this.getAllVertices();
|
||||
const verticesIndices = this.getVerticesIndices();
|
||||
|
||||
// Init matrix with infinities meaning that there is no ways of
|
||||
// getting from one vertex to another yet.
|
||||
const adjacencyMatrix = Array(vertices.length).fill(null).map(() => {
|
||||
return Array(vertices.length).fill(Infinity);
|
||||
});
|
||||
|
||||
// Fill the columns.
|
||||
vertices.forEach((vertex, vertexIndex) => {
|
||||
vertex.getNeighbors().forEach((neighbor) => {
|
||||
const neighborIndex = verticesIndices[neighbor.getKey()];
|
||||
adjacencyMatrix[vertexIndex][neighborIndex] = this.findEdge(vertex, neighbor).weight;
|
||||
});
|
||||
});
|
||||
|
||||
return adjacencyMatrix;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {string}
|
||||
* Get the adjacency matrix of the graph.
|
||||
* @returns {*[][]} - A 2D array representing the adjacency matrix.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Convert the graph to a string representation.
|
||||
* @returns {string} - A string representing the graph's vertices.
|
||||
*/
|
||||
toString() {
|
||||
return Object.keys(this.vertices).toString();
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user