diff --git a/Graphs/Graph.js b/Graphs/Graph.js new file mode 100644 index 0000000000..2a3756a3e6 --- /dev/null +++ b/Graphs/Graph.js @@ -0,0 +1,115 @@ +class Graph { + constructor() { + this.adjacencyMap = {} + } + + addVertex(vertex) { + this.adjacencyMap[vertex] = [] + } + + containsVertex(vertex) { + return typeof this.adjacencyMap[vertex] !== 'undefined' + } + + addEdge(vertex1, vertex2) { + if (this.containsVertex(vertex1) && this.containsVertex(vertex2)) { + this.adjacencyMap[vertex1].push(vertex2) + this.adjacencyMap[vertex2].push(vertex1) + } + } + +/** + * Prints the graph using the given output function. + * + * @param {function(value)} output The output function to use. + */ + + printGraph(output = (value) => console.log(value)) { + const keys = Object.keys(this.adjacencyMap) + for (const i of keys) { + const values = this.adjacencyMap[i] + let vertex = '' + for (const j of values) { + vertex += j + ' ' + } + output(i + ' -> ' + vertex) + } + } + + /** + * Prints the Breadth first traversal of the graph from source. + * + * @param {number} source The source vertex to start BFS. + * @param {function(value)} output The output function to use. + */ + + bfs(source, output = (value) => console.log(value)) { + const queue = [[source, 0]] // level of source is 0 + const visited = new Set() + + while (queue.length) { + const [node, level] = queue.shift() // remove the front of the queue + if (visited.has(node)) { + // visited + continue + } + + visited.add(node) + output(`Visited node ${node} at level ${level}.`) + for (const next of this.adjacencyMap[node]) { + queue.push([next, level + 1]) // level 1 more than current + } + } + } + + /** + * Prints the Depth first traversal of the graph from source. + * + * @param {number} source The source vertex to start DFS. + * @param {function(value)} output The output function to use. + */ + + dfs(source, visited = new Set(), output = (value) => console.log(value)) { + if (visited.has(source)) { + // visited + return + } + + output(`Visited node ${source}`) + visited.add(source) + for (const neighbour of this.adjacencyMap[source]) { + this.dfs(neighbour, visited, output) + } + } +} + +const example = () => { + const g = new Graph() + g.addVertex(1) + g.addVertex(2) + g.addVertex(3) + g.addVertex(4) + g.addVertex(5) + g.addEdge(1, 2) + g.addEdge(1, 3) + g.addEdge(2, 4) + g.addEdge(2, 5) + + // Graph + // 1 -> 2 3 + // 2 -> 1 4 5 + // 3 -> 1 + // 4 -> 2 + // 5 -> 2 + + // Printing the adjacency list + // g.printGraph() + + // Breadth first search at node 1 + g.bfs(1) + + // Depth first search at node 1 + g.dfs(1) +} + +export { Graph, example } diff --git a/Graphs/Graph2.js b/Graphs/Graph2.js new file mode 100644 index 0000000000..cfb1d6b183 --- /dev/null +++ b/Graphs/Graph2.js @@ -0,0 +1,71 @@ +// create a graph class +class Graph { + // defining vertex array and + // adjacent list + + /** + * Create a graph with the number of vertices + * @param {number} noOfVertices the number of vertices of the graph + */ + constructor(noOfVertices) { + this.noOfVertices = noOfVertices + this.AdjList = new Map() + } + + // functions to be implemented + + // addVertex(v) + // addEdge(v, w) + // printGraph() + + // bfs(v) + // dfs(v) + + // add vertex to the graph + addVertex(v) { + // initialize the adjacent list with a + // null array + + this.AdjList.set(v, []) + } + + // add edge to the graph + addEdge(v, w) { + // get the list for vertex v and put the + // vertex w denoting edge between v and w + this.AdjList.get(v).push(w) + + // Since graph is undirected, + // add an edge from w to v also + this.AdjList.get(w).push(v) + } + + // Prints the vertex and adjacency list + +/** + * @param {function(value)} output The output function use + */ + printGraph(output = (value) => console.log(value)) { + // get all the vertices + const getKeys = this.AdjList.keys() + + // iterate over the vertices + for (const i of getKeys) { + // get the corresponding adjacency list + // for the vertex + const getValues = this.AdjList.get(i) + let conc = '' + + // iterate over the adjacency list + // concatenate the values into a string + for (const j of getValues) { + conc += j + ' ' + } + + // print the vertex and its adjacency list + output(i + ' -> ' + conc) + } + } +} + +export { Graph } diff --git a/Graphs/Graph3.js b/Graphs/Graph3.js new file mode 100644 index 0000000000..03185f6e51 --- /dev/null +++ b/Graphs/Graph3.js @@ -0,0 +1,126 @@ +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 + * + * @param {number} start The start vertex. + * @returns {Array} The DFS list. + * + */ + + 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 + * + * @param {number} start The start vertex. + * @returns {Array} The DFS list. + */ + + + 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 + } + +/** + * Return BFS (Breadth First Search) List + * + * @param {number} start The start vertex. + * @returns {Array} The BFS list. +*/ + + 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 }