export default class Graph { /** * @param {boolean} isDirected */ constructor(isDirected = false) { this.vertices = {}; this.edges = {}; this.isDirected = isDirected; } /** * @param {GraphVertex} newVertex * @returns {Graph} */ addVertex(newVertex) { this.vertices[newVertex.getKey()] = newVertex; return this; } /** * @param {string} vertexKey * @returns GraphVertex */ getVertexByKey(vertexKey) { return this.vertices[vertexKey]; } /** * @param {GraphVertex} vertex */ getNeighbors(vertex) { return vertex.getNeighbors(); } /** * @return {GraphVertex[]} */ getAllVertices() { return Object.values(this.vertices); } /** * @return {GraphEdge[]} */ getAllEdges() { return Object.values(this.edges); } /** * @param {GraphEdge} edge * @returns {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 {GraphVertex} startVertex * @param {GraphVertex} endVertex * @return {(GraphEdge|null)} */ findEdge(startVertex, endVertex) { const vertex = this.getVertexByKey(startVertex.getKey()); return vertex.findEdge(endVertex); } /** * @param {string} vertexKey * @returns {GraphVertex} */ findVertexByKey(vertexKey) { if (this.vertices[vertexKey]) { return this.vertices[vertexKey]; } return null; } /** * @return {number} */ getWeight() { return this.getAllEdges().reduce((weight, graphEdge) => { return weight + graphEdge.weight; }, 0); } /** * @return {string} */ toString() { return Object.keys(this.vertices).toString(); } }