From 11faa9b06c991afdea10edac3e43768f711cad83 Mon Sep 17 00:00:00 2001 From: Astolfo Date: Sun, 13 Feb 2022 12:30:58 -0300 Subject: [PATCH] feat/test/ get vertex by key and add isConnected tests --- data-structures/graph/Graph.js | 93 ++++++++++++--- data-structures/graph/__test__/Graph.test.js | 114 ++++++++++++++++--- 2 files changed, 173 insertions(+), 34 deletions(-) diff --git a/data-structures/graph/Graph.js b/data-structures/graph/Graph.js index acd7aeb8..5ee2baad 100755 --- a/data-structures/graph/Graph.js +++ b/data-structures/graph/Graph.js @@ -82,7 +82,7 @@ export default class Graph { * @param {integer} vertexIndex * @returns GraphVertex */ - getVertexByIndex(vertexIndex) { + getVertexByIndex(vertexIndex) { let adjList=this.getAdjacencyList(); return this.vertices[adjList[vertexIndex]]; } @@ -125,6 +125,29 @@ export default class Graph { return Object.values(this.edges); } + /** + * @param {integer} vertexIndex + * @returns GraphVertex + */ + getEdgesByVertexKeys(vertexKeys) { + let edges_from_keys=[] + let edges=this.getAllEdges(); + + for(let i=0; i weight + graphEdge.weight, 0); } + getForwardDegrees() { + const adjList = this.getAdjacencyList(); + + return Object + .values(adjList) + .map((to_neighbours) => { + return to_neighbours.length + }) + } + + getReverseDegrees() { + const adjList = this.getAdjacencyList(1); + + return Object + .values(adjList) + .map((to_neighbours) => { + return to_neighbours.length + }) + } + /** * @return {object} */ @@ -577,33 +620,43 @@ export default class Graph { const n_vertices = this.getNumVertices(); const adjList = this.getAdjacencyList(); const edges = this.getAllEdges(); - - // If there are no edges in the graph, return true + + // If there are no edges in the graph, return false if (edges.length == 0){ - return true; + return false; } // Mark all the vertices as not visited let visited = new Array(n_vertices); - let i; - for (i = 0; i < n_vertices; i++){ + for (let i = 0; i < n_vertices; i++){ visited[i] = false; } - - // Find a vertex with non-zero degree - for (i = 0; i < n_vertices; i++) { - if (adjList[i].length != 0) { - break; - } + + let forward_degrees = this.getForwardDegrees(); + let reverse_degrees = this.getReverseDegrees(); + + let summedDegrees=[] + for(let i=0; i summedDegree==0) + + if(zero_summed_degrees.length!=0) + return false - // Check if all non-zero degree vertices are visited - for (i = 0; i < n_vertices; i++){ - if (visited[i] == false && adjList[i].length > 0){ - return false; + // Find a vertex with non-zero degree + for (let i=0; i 0){ + return false; + } + } } } @@ -1117,6 +1170,10 @@ export default class Graph { } allPaths(from, to) { + if(!this.isCyclic){ + return this.acyclicPaths(); + } + let cycles_venn = this.getCyclesVenn(); let cycle_indices = this.getCycleIndices(); diff --git a/data-structures/graph/__test__/Graph.test.js b/data-structures/graph/__test__/Graph.test.js index 8afc6922..d5412b03 100755 --- a/data-structures/graph/__test__/Graph.test.js +++ b/data-structures/graph/__test__/Graph.test.js @@ -21,6 +21,37 @@ describe('Graph', () => { expect(graph.getVertexByKey(B.getKey())).toEqual(B); }); + it('should get vertex by its index', () => { + const graph = new Graph(); + + const [A, B] = createVertices(['A', 'B']); + + graph.addVertices([A, B]); + + let vertex = graph.getVertexByIndex(0) + + expect(vertex.getKey()).toEqual('A'); + }); + + it('should get edges by vertex keys', () => { + const graph = new Graph(); + let keys = ['A', 'B', 'C']; + + const [A, B, C] = createVertices(keys); + const [AB, BC] = createEdges([[A, B], [B, C]]); + + graph.addEdges([AB, BC]); + + let edges = graph.getEdgesByVertexKeys(keys) + + let edge_keys=[] + edges.forEach((edge) => { + edge_keys.push(edge.getKey()) + }) + + expect(edge_keys).toEqual(['A_B', 'B_C']); + }); + it('should add edges to undirected graph', () => { const graph = new Graph(); @@ -344,6 +375,26 @@ describe('Graph', () => { expect(graph.cyclicCircuits()).toStrictEqual([[1, 2, 4], [1, 2, 5]]); }); + it('should return true for strongly connected graph', () => { + let vertex_keys=['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H'] + + const [A, B, C, D, E, F, G, H] = createVertices(vertex_keys); + + let [AB, AC, CD, BD, + EF, EG, FH, GH, + DE]=createEdges([[A, B], [B, C], [C, D], [D, A], + [E, F], [F, G], [G, H], [H, E], + [D, E]]) + + const graph = new Graph(true); + + graph.addEdges([AB, AC, CD, BD, EF, EG, FH, GH, DE]); + + let SCComponents = graph.getStronglyConnectedComponents(); + + expect(SCComponents).toEqual([[0, 3, 2, 1], [4, 7, 6, 5]]); + }); + it('Bridges in graph', () => { // A directed graph const graph = new Graph(true); @@ -593,22 +644,13 @@ describe('Graph', () => { const graph_ = new Graph(true); // Nodes - const A = new GraphVertex('A'); - const B = new GraphVertex('B'); - const C = new GraphVertex('C'); - const D = new GraphVertex('D'); - const E = new GraphVertex('E'); - const F = new GraphVertex('F'); + let [A, B, C, D, E, F] = createVertices(['A', 'B', 'C', 'D', 'E', 'F']) // Vertices - const AB = new GraphEdge(A, B); - const BC = new GraphEdge(B, C); - const CD = new GraphEdge(C, D); - const CE = new GraphEdge(C, E); - const EB = new GraphEdge(E, B); - const CF = new GraphEdge(C, F); - const FB = new GraphEdge(F, B); - + const [AB, BC, CD, CE, + EB, CF, FB] = new createEdges([[A, B], [B, C], [C, D], [C, E], + [E, B], [C, F], [F, B]]); + // Add edges graph_.addEdges([AB, BC, CD, CE, EB, CF, FB]); @@ -726,7 +768,21 @@ describe('Graph', () => { expect(graph.isConnected()).toEqual(true); }); - it('should return true for graph without edges', () => { + it('should return false for not-connected graph', () => { + const graph = new Graph(true); + + // Nodes + let [A, B, C] = createVertices(['A', 'B', 'C']); + let [AB] = createEdges([[A, B]]); + + // Add edges + graph.addVertices([A, B, C]); + graph.addEdges([AB]); + + expect(graph.isConnected()).toEqual(false); + }); + + it('should return true for connected graph', () => { const graph = new Graph(true); // Nodes @@ -737,11 +793,37 @@ describe('Graph', () => { const E = new GraphVertex('E'); const F = new GraphVertex('F'); - graph.addVertices([A, B, C, D, E, F]) + // Vertices + const AB = new GraphEdge(A, B); + const BC = new GraphEdge(B, C); + const CD = new GraphEdge(C, D); + const CE = new GraphEdge(C, E); + const EB = new GraphEdge(E, B); + const CF = new GraphEdge(C, F); + const FB = new GraphEdge(F, B); + // Add edges + graph.addEdges([AB, BC, CD, CE, EB, CF, FB]); + expect(graph.isConnected()).toEqual(true); }); + it('should return false for graph without edges', () => { + const graph = new Graph(true); + + // Nodes + const A = new GraphVertex('A'); + const B = new GraphVertex('B'); + const C = new GraphVertex('C'); + const D = new GraphVertex('D'); + const E = new GraphVertex('E'); + const F = new GraphVertex('F'); + + graph.addVertices([A, B, C, D, E, F]) + + expect(graph.isConnected()).toEqual(false); + }); + it('should return empty for non-eulerian graph', () => { const graph = new Graph(true);