diff --git a/Data-Structures/Graph/Graph3.js b/Data-Structures/Graph/Graph3.js new file mode 100644 index 000000000..d5a36bf18 --- /dev/null +++ b/Data-Structures/Graph/Graph3.js @@ -0,0 +1,108 @@ +class Graph { + constructor () { + this.adjacencyObject = {} + } + + addVertex (vertex) { + if (!this.adjacencyObject[vertex]) this.adjacencyObject[vertex] = [] + } + + addEdge (vertex1, vertex2) { + this.adjacencyObject[vertex1].push(vertex2) + this.adjacencyObject[vertex2].push(vertex1) + } + + removeEdge (vertex1, vertex2) { + this.adjacencyObject[vertex1] = this.adjacencyObject[vertex1].filter( + (v) => v !== vertex2 + ) + this.adjacencyObject[vertex2] = this.adjacencyObject[vertex2].filter( + (v) => v !== vertex1 + ) + } + + removeVertex (vertex) { + while (this.adjacencyObject[vertex].length) { + const adjacentVertex = this.adjacencyObject[vertex].pop() + this.removeEdge(vertex, adjacentVertex) + } + } + + /** + * Return DFS (Depth First Search) List Using Recursive Method + */ + DFS (start) { + if (!start) return null + + const result = [] + const visited = {} + const adjacencyObject = this.adjacencyObject + + function dfs (vertex) { + if (!vertex) return null + visited[vertex] = true + result.push(vertex) + adjacencyObject[vertex].forEach((neighbor) => { + if (!visited[neighbor]) { + dfs(neighbor) + } + }) + } + + dfs(start) + return result + } + + /** + * Return DFS(Depth First Search) List Using Iteration + */ + DFSIterative (start) { + if (!start) return null + + const stack = [start] + const visited = {} + visited[start] = true + + const result = [] + let currentVertex + + while (stack.length) { + currentVertex = stack.pop() + result.push(currentVertex) + + this.adjacencyObject[currentVertex].forEach((neighbor) => { + if (!visited[neighbor]) { + visited[neighbor] = true + stack.push(neighbor) + } + }) + } + return result + } + + BFS (start) { + if (!start) return null + + const queue = [start] + const visited = {} + visited[start] = true + + let currentVertex + const result = [] + + while (queue.length) { + currentVertex = queue.shift() + result.push(currentVertex) + + this.adjacencyObject[currentVertex].forEach((neighbor) => { + if (!visited[neighbor]) { + visited[neighbor] = true + queue.push(neighbor) + } + }) + } + return result + } +} + +export { Graph } diff --git a/Data-Structures/Graph/test/Graph3.test.js b/Data-Structures/Graph/test/Graph3.test.js new file mode 100644 index 000000000..d10cc8da2 --- /dev/null +++ b/Data-Structures/Graph/test/Graph3.test.js @@ -0,0 +1,75 @@ +import { Graph } from '../Graph3' + +describe('Test Graph3', () => { + const g = new Graph() + + // Add Vertices + g.addVertex('A') + g.addVertex('B') + g.addVertex('C') + g.addVertex('D') + g.addVertex('E') + g.addVertex('F') + + // Add Edges + g.addEdge('A', 'B') + g.addEdge('A', 'C') + g.addEdge('B', 'D') + g.addEdge('C', 'E') + g.addEdge('D', 'E') + g.addEdge('D', 'F') + g.addEdge('E', 'F') + + /** + * A - B - D + * | / \ + * C - - E - F + * + * DFS(Iterative): A-C-E-F-D-B + * DFS(Recursive): A-B-D-E-C-F + * BFS: A-B-C-D-E-F + */ + it('Check iterative DFS List', () => { + const iterativeDFSList = g.DFSIterative('A') + expect(iterativeDFSList).toEqual(['A', 'C', 'E', 'F', 'D', 'B']) + }) + + it('Check recursive DFS List', () => { + const recursiveDFSList = g.DFS('A') + expect(recursiveDFSList).toEqual(['A', 'B', 'D', 'E', 'C', 'F']) + }) + + it('Check BFS List', () => { + const BFSList = g.BFS('A') + expect(BFSList).toEqual(['A', 'B', 'C', 'D', 'E', 'F']) + }) + + /** + * Test After Remove 'B' Vertex + * A D + * | / \ + * C - - E - F + * + * DFS(Iterative): A-C-E-F-D + * DFS(Recursive): A-C-E-D-F + * BFS: A-C-E-D-F + */ + + it('Check iterative DFS List After Removing Vertex B', () => { + g.removeVertex('B') + const iterativeDFSList = g.DFSIterative('A') + expect(iterativeDFSList).toEqual(['A', 'C', 'E', 'F', 'D']) + }) + + it('Check recursive DFS List After Removing Vertex B', () => { + g.removeVertex('B') + const recursiveDFSList = g.DFS('A') + expect(recursiveDFSList).toEqual(['A', 'C', 'E', 'D', 'F']) + }) + + it('Check BFS List After Removing Vertex B', () => { + g.removeVertex('B') + const BFSList = g.BFS('A') + expect(BFSList).toEqual(['A', 'C', 'E', 'D', 'F']) + }) +})