
- Javascript Basics Tutorial
- Javascript - Home
- Javascript - Overview
- Javascript - Syntax
- Javascript - Enabling
- Javascript - Placement
- Javascript - Variables
- Javascript - Operators
- Javascript - If...Else
- Javascript - Switch Case
- Javascript - While Loop
- Javascript - For Loop
- Javascript - For...in
- Javascript - Loop Control
- Javascript - Functions
- Javascript - Events
- Javascript - Cookies
- Javascript - Page Redirect
- Javascript - Dialog Boxes
- Javascript - Void Keyword
- Javascript - Page Printing
- JavaScript Objects
- Javascript - Objects
- Javascript - Number
- Javascript - Boolean
- Javascript - Strings
- Javascript - Arrays
- Javascript - Date
- Javascript - Math
- Javascript - RegExp
- Javascript - HTML DOM
- JavaScript Advanced
- Javascript - Error Handling
- Javascript - Validations
- Javascript - Animation
- Javascript - Multimedia
- Javascript - Debugging
- Javascript - Image Map
- Javascript - Browsers
- JavaScript Useful Resources
- Javascript - Questions And Answers
- Javascript - Quick Guide
- Javascript - Functions
- Javascript - Resources
Implementation of Graph in JavaScript
A graph is a non-linear data structure that represents a set of vertices (also called nodes) and the relationships (or edges) between them. Vertices represent entities or objects, while edges represent the relationships or connections between the vertices. Graphs can be used to model many different types of relationships, such as social networks, transportation systems, or flow of information.
There are two main types of graphs: directed graphs (also called digraphs) and undirected graphs. In a directed graph, edges have a direction and can only be traversed in one direction, from the starting vertex to the end vertex. In an undirected graph, edges have no direction and can be traversed in both directions.
Implementation of Graph in JavaScript
Graphs can be implemented using Adjacency Matrix or Adjacency List. Here, we will impletnent graph in JavaScript using Adjacency List.
Creating the graph class
Here we create the blue print of the graph class.
class Graph { constructor() { this.adjacencyList = {}; } }
Adding a Vertex
This function adds a new vertex (or node) to the graph by creating a new key in the adjacencyList object with an empty array as its value. The new vertex will be the key and the empty array will be used to store its neighbors.
addVertex(vertex) { if (!this.adjacencyList[vertex]) this.adjacencyList[vertex] = []; }
Adding an Edge
This function adds a new edge between two vertices. It takes two arguments, vertex1 and vertex2, and adds vertex2 to the array of neighbors of vertex1, and vice versa. This creates a connection between the two vertices.
addEdge(vertex1, vertex2) { this.adjacencyList[vertex1].push(vertex2); this.adjacencyList[vertex2].push(vertex1); }
Print the Graph
This function logs the graph to the console. It iterates through each vertex in the adjacencyList object and logs the vertex followed by its neighbors.
print() { for (const [vertex, edges] of Object.entries(this.adjacencyList)) { console.log(`${vertex} -> ${edges.join(", ")}`); } }
Example
In below example, we define a graph and add vertices and edges to the graph. Finally print the graph.
class Graph { constructor() { this.adjacencyList = {}; } addVertex(vertex) { if (!this.adjacencyList[vertex]) this.adjacencyList[vertex] = []; } addEdge(vertex1, vertex2) { this.adjacencyList[vertex1].push(vertex2); this.adjacencyList[vertex2].push(vertex1); } print() { for (const [vertex, edges] of Object.entries(this.adjacencyList)) { console.log(`${vertex} -> ${edges.join(", ")}`); } } } const graph = new Graph(); graph.addVertex("A"); graph.addVertex("B"); graph.addVertex("C"); graph.addVertex("D"); graph.addEdge("A", "B"); graph.addEdge("A", "C"); graph.addEdge("B", "D"); graph.addEdge("C", "D"); console.log("Graph:"); graph.print();
Output
Graph: A -> B, C B -> A, D C -> A, D D -> B, C
Removing an Edge
This function removes an edge between two vertices. It takes two arguments, vertex1 and vertex2, and filters out vertex2 from the array of neighbors of vertex1 and vice versa.
removeEdge(vertex1, vertex2) { this.adjacencyList[vertex1] = this.adjacencyList[vertex1].filter( (v) => v !== vertex2 ); this.adjacencyList[vertex2] = this.adjacencyList[vertex2].filter( (v) => v !== vertex1 ); }
Removing a Vertex
This function removes a vertex from the graph. It takes a vertex argument and first removes all the edges connected to the vertex. Then, it deletes the key from the adjacencyList object.
removeVertex(vertex) { while (this.adjacencyList[vertex].length) { const adjacentVertex = this.adjacencyList[vertex].pop(); this.removeEdge(vertex, adjacentVertex); } delete this.adjacencyList[vertex]; }
Example
In the below example, we define a graph and add vertices and edges, and print the graph. We remove an edge AC from the graph and finally print the resultant graph.
class Graph { constructor() { this.adjacencyList = {}; } addVertex(vertex) { if (!this.adjacencyList[vertex]) this.adjacencyList[vertex] = []; } addEdge(vertex1, vertex2) { this.adjacencyList[vertex1].push(vertex2); this.adjacencyList[vertex2].push(vertex1); } removeEdge(vertex1, vertex2) { this.adjacencyList[vertex1] = this.adjacencyList[vertex1].filter( (v) => v !== vertex2 ); this.adjacencyList[vertex2] = this.adjacencyList[vertex2].filter( (v) => v !== vertex1 ); } removeVertex(vertex) { while (this.adjacencyList[vertex].length) { const adjacentVertex = this.adjacencyList[vertex].pop(); this.removeEdge(vertex, adjacentVertex); } delete this.adjacencyList[vertex]; } print() { for (const [vertex, edges] of Object.entries(this.adjacencyList)) { console.log(`${vertex} -> ${edges.join(", ")}`); } } } const graph = new Graph(); graph.addVertex("A"); graph.addVertex("B"); graph.addVertex("C"); graph.addVertex("D"); graph.addEdge("A", "B"); graph.addEdge("A", "C"); graph.addEdge("B", "D"); graph.addEdge("C", "D"); console.log("Initial Graph:"); graph.print(); console.log("
Graph after removal of edge AC:") graph.removeEdge("A","C"); graph.print();
Output
Initial Graph: A -> B, C B -> A, D C -> A, D D -> B, C Graph after removal of edge AC: A -> B B -> A, D C -> D D -> B, C
Graph Traversal Methods
Graph traversal refers to the process of visiting all the vertices (or nodes) of a graph and processing the information associated with them. Graph traversal is an important operation in graph algorithms and is used for tasks such as finding the shortest path between two nodes, detecting cycles, and finding connected components.
There are two main approaches to graph traversal: breadth-first search (BFS) and depth-first search (DFS)
A. Breadth First Search (BFS)
It is implemented using breadthFirstSearch() function. This function implements the breadth-first search algorithm and takes a start argument, which is the starting vertex. It uses a queue to keep track of the vertices to be visited, a result array to store the visited vertices, and a visited object to keep track of the vertices that have already been visited. The function starts by adding the start vertex to the queue and marking it as visited. Then, while the queue is not empty, it takes the first vertex from the queue, adds it to the result array, and marks it as visited. It then adds all of its unvisited neighbors to the queue. This process continues until all vertices have been visited, and the result array is returned as the result of the BFS.
breadthFirstSearch(start) { const queue = [start]; const result = []; const visited = {}; let currentVertex; visited[start] = true; while (queue.length) { currentVertex = queue.shift(); result.push(currentVertex); this.adjacencyList[currentVertex].forEach((neighbor) => { if (!visited[neighbor]) { visited[neighbor] = true; queue.push(neighbor); } }); } return result; } }
B. Depth First Search
The depthFirstSearch method implements the DFS algorithm by using a recursive inner function dfs that takes a vertex as an argument. The function keeps track of the visited vertices using an object visited and adds each visited vertex to a result array. The function first marks the current vertex as visited and adds it to the result array. Then, it iterates over all the neighbors of the current vertex and calls the dfs function recursively for each unvisited neighbor. The process continues until all vertices have been visited and the result array is returned as the result of the DFS.
depthFirstSearch(start) { const result = []; const visited = {}; const adjacencyList = this.adjacencyList; (function dfs(vertex) { if (!vertex) return null; visited[vertex] = true; result.push(vertex); adjacencyList[vertex].forEach(neighbor => { if (!visited[neighbor]) { return dfs(neighbor); } }); })(start); return result; }
Example
In the below example, we demonstrate the Breadth First Search (BFS) and Depth First Search (DFS).
class Graph { constructor() { this.adjacencyList = {}; } addVertex(vertex) { if (!this.adjacencyList[vertex]) this.adjacencyList[vertex] = []; } addEdge(vertex1, vertex2) { this.adjacencyList[vertex1].push(vertex2); this.adjacencyList[vertex2].push(vertex1); } print() { for (const [vertex, edges] of Object.entries(this.adjacencyList)) { console.log(`${vertex} -> ${edges.join(", ")}`); } } breadthFirstSearch(start) { const queue = [start]; const result = []; const visited = {}; let currentVertex; visited[start] = true; while (queue.length) { currentVertex = queue.shift(); result.push(currentVertex); this.adjacencyList[currentVertex].forEach((neighbor) => { if (!visited[neighbor]) { visited[neighbor] = true; queue.push(neighbor); } }); } return result; } depthFirstSearch(start) { const result = []; const visited = {}; const adjacencyList = this.adjacencyList; (function dfs(vertex) { if (!vertex) return null; visited[vertex] = true; result.push(vertex); adjacencyList[vertex].forEach(neighbor => { if (!visited[neighbor]) { return dfs(neighbor); } }); })(start); return result; } } const graph = new Graph(); graph.addVertex("A"); graph.addVertex("B"); graph.addVertex("C"); graph.addVertex("D"); graph.addEdge("A", "B"); graph.addEdge("A", "C"); graph.addEdge("B", "D"); graph.addEdge("C", "D"); console.log("Initial Graph:"); graph.print(); console.log("
BFS: "+graph.breadthFirstSearch('A')); console.log("DFS: "+graph.depthFirstSearch('A'));
Output
Initial Graph: A -> B, C B -> A, D C -> A, D D -> B, C BFS: A,B,C,D DFS: A,B,D,C
Conclusion
A graph is a useful data structure that can be used to represent relationships and connections between objects. Implementing a graph in JavaScript can be done using a variety of techniques, including using an adjacency list or adjacency matrix. The Graph class demonstrated in this answer uses an adjacency list representation, where each vertex is stored as a key in an object and its corresponding edges are stored in an array as the value for that key.
The Graph class implements methods for adding vertices and edges to the graph, as well as for printing the graph and performing depth-first search and breadth-first search traversals.
- Related Articles
- Implementation of Stack in JavaScript
- Implementation of Queue in JavaScript
- Implementation of LinkedList in Javascript
- Graph Traversals in Javascript
- Graph Data Structure in Javascript
- Creating a Graph in Javascript
- Complete Graph Class in Javascript
- Implementation of Dynamic Array in Python
- Array implementation of queue in C++
- Recursive Implementation of atoi() in C++
- Implementation of Static Routing in Cisco
- The implementation of import in Python (importlib)
- Implementation of a Falling Matrix in C++
- Python - Implementation of Polynomial Regression
- Implementation of connection-oriented services
