├── BFS.cpp ├── DijkstrasAlgorithm.cpp ├── IterativeDFS.cpp ├── PrimsAlgorithm.cpp ├── README.md ├── RecursiveDFS.cpp ├── ShortestPathBFS.cpp ├── TopologicalSort.cpp ├── images ├── DAG.png ├── connected-graph.png ├── directed-graph.png ├── simple-graph.png ├── strongly-connected.png └── undirected-graph.png └── kruskals.cpp /BFS.cpp: -------------------------------------------------------------------------------- 1 | // Author: Aakash Prabhu 2 | #include 3 | #include 4 | #include 5 | using namespace std; 6 | 7 | // BFS Traversal of an undirected and unweighted graph. 8 | void createAndAddEdge(vector adjList[], int u, int v){ 9 | adjList[u].push_back(v); 10 | adjList[v].push_back(u); // do this because undirected graph 11 | } // createAndAddEdge(vector List[], int u, int v) 12 | 13 | void BFS(vector adjList[], vector visitedVertex, int source){ 14 | queue Q; //set up Queue for BFS 15 | int v; 16 | Q.push(source); 17 | while (!Q.empty()){ 18 | v = Q.front(); 19 | visitedVertex.at(v) = true; 20 | Q.pop(); 21 | cout << v << " "; // Print Vertex 22 | for (vector::iterator it = adjList[v].begin(); it != adjList[v].end(); it++) // Visit all children 23 | if (!visitedVertex.at(*it)){ 24 | Q.push(*it); // Push unvisted vertex onto the queue 25 | visitedVertex.at(*it) = true; 26 | } // if not visited 27 | } // While Queue is not empty 28 | cout << endl; 29 | } // BFS 30 | 31 | int main (void){ 32 | // Idea is to implement the adjacency list as an array of vectors: 33 | const int numVertices = 6; // 6 vertices (0,1,2,3,4,5) 34 | int source = 0; 35 | vector adjList[numVertices]; // Create an array of vectors 36 | vector visitedVertex(numVertices, false); 37 | createAndAddEdge(adjList, 0, 1); 38 | createAndAddEdge(adjList, 0, 2); 39 | createAndAddEdge(adjList, 1, 5); 40 | createAndAddEdge(adjList, 2, 3); 41 | createAndAddEdge(adjList, 2, 4); 42 | createAndAddEdge(adjList, 3, 3); 43 | createAndAddEdge(adjList, 4, 4); 44 | createAndAddEdge(adjList, 5, 5); 45 | BFS(adjList, visitedVertex, source); // Perform BFS given graph G and a source s 46 | //Should Print: 0 1 2 5 3 4 47 | 48 | } // main() 49 | -------------------------------------------------------------------------------- /DijkstrasAlgorithm.cpp: -------------------------------------------------------------------------------- 1 | // Author: Aakash Prabhu 2 | #include 3 | #include 4 | #include // To set up priority queue 5 | #include // To use std::greater -> This will prove to be useful in picking the minimum weight 6 | using namespace std; 7 | 8 | /* Uses Dijkstra's Algorithm to find the Shortest Path from an arbitrary vertex to all other vertices 9 | * Since the following version of Dijkstra's is implemented using a min-priority queue, 10 | * the time complexity of the algorithm is O(V + ElogV). 11 | */ 12 | 13 | typedef pair Pair; // First = Weight & Second = Vertex 14 | const int numVertices = 6; // 6 vertices (0,1,2,3,4,5) 15 | vector visitedVertex(numVertices, false); 16 | int ShortestPath[numVertices]; // Have an array to store the shortest path 17 | 18 | void createAndAddEdge(vector adjList[], int u, int weight, int v){ 19 | adjList[u].push_back(make_pair(weight, v)); 20 | } // createAndAddEdge(vector List[], int u, int v, int weight) 21 | 22 | void DijkstrasAlgorithm(vector adjList[], int source){ 23 | priority_queue, greater > PQ; // Set up priority queue 24 | Pair info; 25 | int weight; 26 | ShortestPath[source] = 0; // Set source distance to zero 27 | 28 | for (int i = 0; i < numVertices; i++) 29 | if (i != source) 30 | ShortestPath[i] = 100000; // Initialize everything else to +infinity 31 | 32 | PQ.push(make_pair(0, source)); // Source has weight 0; 33 | 34 | while (!PQ.empty()){ 35 | info = PQ.top(); // Use to get minimum weight 36 | PQ.pop(); // Pop before checking for cycles 37 | source = info.second; // get the vertex 38 | weight = info.first; // current distance 39 | 40 | if (visitedVertex.at(source)) // Check for cycle 41 | continue; // Already accounted for it, move on 42 | 43 | visitedVertex.at(source) = true; // Else, mark the vertex so that we won't have to visit it again 44 | 45 | for (vector::iterator it = adjList[source].begin(); it != adjList[source].end(); it++) 46 | if ((weight + (it->first)) < ShortestPath[it->second]){ // Check if we can do better 47 | ShortestPath[it->second] = weight + (it->first); // Update new distance 48 | PQ.push(make_pair(ShortestPath[it->second], it->second)); // Push vertex and weight onto Priority Queue 49 | } // Update distance 50 | } // While Priority Queue is not empty 51 | } // DijkstrasAlgorithm 52 | 53 | // Driver function 54 | int main (void){ 55 | 56 | int source = 0; 57 | vector adjList[numVertices]; // Create an array of vectors that contain pairs of adjacent vertex and weight 58 | createAndAddEdge(adjList, 0, 5, 1); 59 | createAndAddEdge(adjList, 0, 10, 3); 60 | createAndAddEdge(adjList, 1, 2, 2); 61 | createAndAddEdge(adjList, 1, 10, 5); 62 | createAndAddEdge(adjList, 1, 5, 4); 63 | createAndAddEdge(adjList, 2, 1, 3); 64 | createAndAddEdge(adjList, 2, 5, 4); 65 | createAndAddEdge(adjList, 2, 3, 0); 66 | createAndAddEdge(adjList, 4, 2, 5); 67 | DijkstrasAlgorithm(adjList, source); 68 | 69 | cout << "Shortest path from source vertex " << source << ": "; 70 | for (int i = 0; i < numVertices; i++) 71 | cout << ShortestPath[i] << " "; 72 | cout << endl; 73 | 74 | } // main() 75 | -------------------------------------------------------------------------------- /IterativeDFS.cpp: -------------------------------------------------------------------------------- 1 | // Author: Aakash Prabhu 2 | #include 3 | #include 4 | #include 5 | using namespace std; 6 | 7 | // DFS Traversal of an undirected and unweighted graph. 8 | void createAndAddEdge(vector adjList[], int u, int v){ 9 | adjList[u].push_back(v); 10 | adjList[v].push_back(u); // do this because undirected graph 11 | } // createAndAddEdge(vector List[], int u, int v) 12 | 13 | void DFS(vector adjList[], vector visitedVertex, int source){ 14 | stack S; //set up Queue for BFS 15 | int v; 16 | S.push(source); 17 | while (!S.empty()){ 18 | v = S.top(); 19 | visitedVertex.at(v) = true; 20 | S.pop(); 21 | cout << v << " "; // Print Vertex 22 | for (vector::iterator it = adjList[v].begin(); it != adjList[v].end(); it++) // Go as far as we can go and then backtrack 23 | if (!visitedVertex.at(*it)){ 24 | S.push(*it); // Push unvisted vertex onto the stack 25 | visitedVertex.at(*it) = true; 26 | } // if not visited 27 | } // While Stack is not empty 28 | cout << endl; 29 | } // DFS 30 | 31 | int main (void){ 32 | // Idea is to implement the adjacency list as an array of vectors: 33 | const int numVertices = 5; // 6 vertices (0,1,2,3,4,5) 34 | int source = 0; 35 | vector adjList[numVertices]; // Create an array of vectors 36 | vector visitedVertex(numVertices, false); 37 | createAndAddEdge(adjList, 0, 1); 38 | createAndAddEdge(adjList, 0, 2); 39 | createAndAddEdge(adjList, 1, 3); 40 | createAndAddEdge(adjList, 1, 4); 41 | createAndAddEdge(adjList, 3, 3); 42 | createAndAddEdge(adjList, 4, 4); 43 | createAndAddEdge(adjList, 2, 2); 44 | DFS(adjList, visitedVertex, source); // Perform DFS given graph G and a source s 45 | //Should Print: 0 2 1 4 3 46 | 47 | } // main() 48 | -------------------------------------------------------------------------------- /PrimsAlgorithm.cpp: -------------------------------------------------------------------------------- 1 | // Author: Aakash Prabhu 2 | #include 3 | #include 4 | #include // To set up priority queue 5 | #include // To use std::greater -> This will prove to be useful in picking the minimum weight 6 | using namespace std; 7 | 8 | /* Program that uses Prims Algorithm to generate a Minimum Spanning Tree 9 | * and hence find the minimum cost to connect all the vertices 10 | */ 11 | 12 | typedef pair Pair; // First = Weight & Second = Vertex 13 | const int numVertices = 4; // 4 vertices (0,1,2,3) 14 | vector visitedVertex(numVertices, false); 15 | 16 | void createAndAddEdge(vector adjList[], int u, int weight, int v){ 17 | adjList[u].push_back(make_pair(weight, v)); 18 | adjList[v].push_back(make_pair(weight, u)); // do this because undirected graph 19 | } // createAndAddEdge(vector List[], int u, int v, int weight) 20 | 21 | void PrimsAlgorithm(vector adjList[], int source){ 22 | priority_queue, greater > PQ; // Set up priority queue 23 | Pair info; 24 | int minCost = 0; 25 | PQ.push(make_pair(0, source)); // Source has weight 0; 26 | while (!PQ.empty()){ 27 | info = PQ.top(); // Use to get minimum weight 28 | source = info.second; // get the vertex 29 | PQ.pop(); // Pop before checking for cycles 30 | if (visitedVertex.at(source)) // Check for cycle 31 | continue; // Already accounted for it, move on 32 | visitedVertex.at(source) = true; // Else, mark the vertex so that we won't have to visit it again 33 | cout << "Mark vertex " << info.second << " and add weight " << info.first << endl; 34 | minCost += info.first; // Add to minCost 35 | for (vector::iterator it = adjList[source].begin(); it != adjList[source].end(); it++) // Visit all children 36 | if (!visitedVertex.at(it->second)) // If vertex hasn't been visited already 37 | PQ.push(make_pair(it->first, it->second)); // Push vertex and weight onto Priority Queue 38 | } // While Priority Queue is not empty 39 | cout << "Minimum cost to connect all vertices : " << minCost << endl; 40 | } // PrimsAlgorithm 41 | 42 | int main (void){ 43 | // Idea is to implement the adjacency list as an array of vectors: 44 | int source = 0; 45 | vector adjList[numVertices]; // Create an array of vectors that contain pairs of adjacent vertex and weight 46 | createAndAddEdge(adjList, 0, 1, 1); 47 | createAndAddEdge(adjList, 0, 2, 3); 48 | createAndAddEdge(adjList, 1, 4, 2); 49 | createAndAddEdge(adjList, 1, 3, 3); 50 | createAndAddEdge(adjList, 2, 5, 3); 51 | PrimsAlgorithm(adjList, source); // Generate MST and find minCost 52 | // Minimum Cost should be 7; 53 | 54 | } // main() 55 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Graph Algorithms :fire: :fire: 2 | 3 | ![MIT](https://img.shields.io/github/license/mashape/apistatus.svg) 4 | 5 | ![Undirected Graph](images/simple-graph.png) 6 | 7 | C++ implementations of various graph algorithms such as: Graph Traversals 8 | (BFS, DFS), Topological Sort, Shortest Path, and Minimum Spanning Trees. 9 | 10 | ## Purpose 11 | 12 | I wrote my own implementations of these graph algorithms to better understand 13 | how graph algorithms work. 14 | 15 | Graph theory is one of the fundamental concepts in Computer Science and often 16 | show up in technical interviews. I wrote this with the intent for people 17 | to study and review the implementations of such algorithms. I've also written 18 | up the high level idea and included the run times with explanations. 19 | 20 | This repository contains everything you could be tested with regards to 21 | graph theory in a technical interview. 22 | 23 | ## Introduction to Graphs 24 | 25 | ### Basic Definition 26 | * A graph, *G* is an ordered pair of the form, `G = (V, E)` where *V* is a set 27 | of vertices and *E* is a set of edges through which vertices are connected. 28 | A graph may be _directed_ or _undirected_. 29 | 30 | Here is an example of a simple undirected graph: 31 | 32 | ![Undirected Graph](images/undirected-graph.png) 33 | 34 | Here is a simple directed graph: 35 | 36 | ![Directed Graph](images/directed-graph.png) 37 | 38 | ### Sparse vs Dense Graphs 39 | 40 | If _|E| ≈ |V|2_ (which is the maximum number of edges in a graph), 41 | then the graph is said to be **dense** 42 | 43 | If _|E| ≈ |V|_, then the graph is said to be **sparse** 44 | 45 | ### Connectivity of Graphs 46 | 47 | * A graph is said to be **connected** if there exists a path between every pair 48 | of vertices in the graph. 49 | 50 | Here is a connected graph: 51 | 52 | ![Connected Graph](images/connected-graph.png) 53 | 54 | * A graph is said to be **strongly connected** if every vertex can be reached 55 | from every other vertex. 56 | 57 | Here is a strongly connected graph: 58 | 59 | ![Strongly Connected Graph](images/strongly-connected.png) 60 | 61 | ### Cycles in Graphs 62 | 63 | A directed graph is said to be **acyclic** if there are no loops within the 64 | directed graph. 65 | 66 | Here is an example of a directed graph: 67 | 68 | ![DAG](images/DAG.png) 69 | 70 | ### Breadth First Search (BFS): 71 | 72 | BFS is one of the most common and widely used traversing algorithms for graphs. 73 | As the name suggests, you traverse the graph in layers. Start BFS from an 74 | arbitrary vertex thus exploring its neighboring nodes. Continue to do this till 75 | you have traversed all of the vertices in the graph. The fundamental idea behind 76 | a BFS traversal is that you must visit the vertex exactly once! To do this, just 77 | mark which vertex you have visited and which one's you haven't using an array. 78 | To visit neighboring vertices, we make use of a queue. Since we enqueue each 79 | vertex at most once, the overall time complexity is *O(|V| + |E|)*. 80 | 81 | ### Depth First Search (DFS): 82 | 83 | Depth First Search is one of the most common recursive algorithm for graph 84 | traversals. The idea behind DFS is to go as far as possible and then backtrack. 85 | Once you have reached a vertex with no more neighbors that are unvisited, you 86 | go backwards to find a vertex that still has unvisited neighbors. 87 | 88 | If you're not a fan of recursion, the DFS algorithm can be implemented by just 89 | altering the BFS code. Instead of using a queue, you would use a stack. 90 | The LIFO feature of a stack allows us to go as far as possible and then lets us 91 | backtrack. Graph traversals really depend on the data structure you use. 92 | The overall time complexity remains the same - *O(|V| + |E|)*. 93 | 94 | 95 | ![BFS vs DFS](https://raw.githubusercontent.com/kdn251/interviews/master/images/dfsbfs.gif) 96 | 97 | ### Topological Sort: 98 | 99 | The topological sort is an algorithm that "sorts" vertices only in a 100 | ***Directed Acyclic Graph***. We make use of the concept of in-degree for each 101 | vertex to implement the topological sort algorithm. The basic idea of the 102 | algorithm is that if there is a vertex **A** with 0 in-degree and is *directed* 103 | to another vertex **B**, then **A** comes before **B** in the graph. 104 | 105 | The algorithm is implemented using a simple BFS traversal with the added 106 | condition that the vertex is enqueued only if the in-degree is 0. Since a BFS 107 | traversal is used, the overall time complexity is simply *O(|V| + |E|)*. 108 | 109 | ### Shortest Path using BFS: 110 | 111 | The shortest path between two vertices in a graph is a path such that the total 112 | sum of edge weights in the path connecting the two vertices is minimum. If we 113 | are given a graph with constant edge weights, then we can just use BFS to solve 114 | the problem. 115 | 116 | However, practical problems have varying edge weights and thus, 117 | we need to make use of more complex algorithms. 118 | One such algorithm is ***Dijkstra's Algorithm*** 119 | 120 | ### Dijkstra's Algorithm: 121 | 122 | Dijkstra's algorithm is arguably one of the most common algorithm used to find 123 | the shortest path between the source vertex to every other vertex in the graph. 124 | The most common data structure used to implement this algorithm is a 125 | min-priority queue. As we enqueue each unvisited vertex, we pop from the 126 | priority queue according to the minimum weight (This technique is also known as 127 | a greedy algorithm). We push onto the priority queue if we can find a better 128 | path (smaller edge weight). The overall time complexity of Dijkstra's algorithm 129 | is *O(V2)* but is reduced to 130 | *O(|V| + |E|log|V|)* when implemented using a min-priority queue. 131 | 132 | 133 | ![](https://raw.githubusercontent.com/kdn251/interviews/master/images/dijkstra.gif) 134 | ### Minimum Spanning Trees (MST): 135 | 136 | A spanning tree is essentially a tree that connects all the vertices in a graph 137 | and is a subgraph of the original graph, G. A minimum spanning tree on the other 138 | hand is a tree that connects all vertices in a graph with a minimum cost 139 | (or minimum edge weights). One of the most common algorithm to find the MST of a 140 | graph is ***Prim's Algorithm***. In this algorithm, we make use of a priority 141 | queue. The algorithm works very similar to Dijkstra's algorithm but does not 142 | make use of a cumulative edge weight. As we visit every vertex, we pick the edge 143 | that has the minimum weight from that vertex and we add it to the spanning tree. 144 | As this algorithm makes use of a min-priority queue, 145 | the overall time complexity is *O(|V| + |E|log|V|)*. 146 | 147 | ![](https://raw.githubusercontent.com/kdn251/interviews/master/images/prim.gif) 148 | 149 | ## Time Complexity Cheatsheet 150 | 151 | | Algorithm | Time Complexity | Notes | 152 | | :------------- | :------------- | :------------- | 153 | | **BFS** | *O(V + E)* | Uses a queue | 154 | | **DFS** | *O(V + E)* | Uses a stack | 155 | | **Topological Sort** | *O(V + E)* | Use when graph is a _DAG_ | 156 | | **Dijkstra's Algorithm** | *O(V + ElogV)* |Implemented using a min priority queue| 157 | | **Prim's Algorithm** | *O(V + ElogV)* |Implemented using a min priority queue| 158 | 159 | 160 | 161 | ## References 162 | 163 | * GIFs are taken from [here](https://github.com/kdn251/interviews). 164 | -------------------------------------------------------------------------------- /RecursiveDFS.cpp: -------------------------------------------------------------------------------- 1 | // Author: Aakash Prabhu 2 | #include 3 | #include 4 | using namespace std; 5 | 6 | // Recursive DFS Traversal of an undirected and unweighted graph. 7 | void createAndAddEdge(vector adjList[], int u, int v){ 8 | adjList[u].push_back(v); 9 | adjList[v].push_back(u); // do this because undirected graph 10 | } // createAndAddEdge(vector List[], int u, int v) 11 | 12 | void RecursiveDFS(vector adjList[], vector visitedVertex, int source){ 13 | visitedVertex.at(source) = true; 14 | cout << source << " "; // Print Vertex 15 | for (vector::iterator it = adjList[source].begin(); it != adjList[source].end(); it++) 16 | if (!visitedVertex[*it]) 17 | RecursiveDFS(adjList, visitedVertex, *it); // Go as far as possible by recursing. 18 | } // DFS 19 | 20 | int main (void){ 21 | // Idea is to implement the adjacency list as an array of vectors: 22 | const int numVertices = 5; // 6 vertices (0,1,2,3,4,5) 23 | int source = 0; 24 | vector adjList[numVertices]; // Create an array of vectors 25 | vector visitedVertex(numVertices, false); // have a visted vector initialized to false 26 | createAndAddEdge(adjList, 0, 1); 27 | createAndAddEdge(adjList, 0, 2); 28 | createAndAddEdge(adjList, 1, 3); 29 | createAndAddEdge(adjList, 1, 4); 30 | createAndAddEdge(adjList, 3, 3); // Do this because no children! 31 | createAndAddEdge(adjList, 4, 4); 32 | createAndAddEdge(adjList, 2, 2); 33 | RecursiveDFS(adjList, visitedVertex, source); // Perform DFS given graph G and a source s 34 | cout << endl; 35 | //Should Print: 0 1 3 4 2 36 | 37 | } // main() 38 | -------------------------------------------------------------------------------- /ShortestPathBFS.cpp: -------------------------------------------------------------------------------- 1 | // Author: Aakash Prabhu 2 | #include 3 | #include 4 | #include 5 | using namespace std; 6 | 7 | /* Find the shortest path for an unweighted, undirected graph 8 | * We will use BFS to traverse the graph. 9 | * Shortest Path using only BFS will work if there are no cycles and if the graph is unweighted or if all edges have same weight 10 | */ 11 | 12 | void createAndAddEdge(vector adjList[], int u, int v){ 13 | adjList[u].push_back(v); 14 | adjList[v].push_back(u); // do this because undirected graph 15 | } // createAndAddEdge(vector List[], int u, int v) 16 | 17 | void ShortestPath(vector adjList[], vector visitedVertex, int source){ 18 | int v; 19 | queue Q; //set up Queue for BFS 20 | vector ShortestPaths(visitedVertex.size()); 21 | ShortestPaths.at(source) = 0; 22 | for (int i = 0; i < ShortestPaths.size(); i++) 23 | if (i != source) 24 | ShortestPaths.at(i) = 1000000; // All other distances have been set to +infinity 25 | Q.push(source); 26 | 27 | while (!Q.empty()){ 28 | v = Q.front(); 29 | visitedVertex.at(v) = true; 30 | Q.pop(); 31 | for (vector::iterator it = adjList[v].begin(); it != adjList[v].end(); it++) // Visit all children 32 | if (!visitedVertex.at(*it)){ 33 | Q.push(*it); // Push unvisted vertex onto the queue 34 | 35 | if (ShortestPaths.at(v) + 1 < ShortestPaths.at(*it)) 36 | ShortestPaths.at(*it) = ShortestPaths.at(v) + 1; // Get new distance 37 | visitedVertex.at(*it) = true; 38 | } // if not visited 39 | } // While Queue is not empty 40 | cout << "Shortest paths from " << source << ": "; 41 | for (int i = 0; i < ShortestPaths.size(); i++) 42 | cout << ShortestPaths.at(i) << " "; 43 | cout << endl; 44 | } // ShortestPath 45 | 46 | // Driver function 47 | int main (void){ 48 | const int numVertices = 6; // 6 vertices (0,1,2,3,4,5) 49 | int source = 0; 50 | vector adjList[numVertices]; // Create an array of vectors 51 | vector visitedVertex(numVertices, false); 52 | createAndAddEdge(adjList, 0, 1); 53 | createAndAddEdge(adjList, 1, 2); 54 | createAndAddEdge(adjList, 1, 5); 55 | createAndAddEdge(adjList, 2, 3); 56 | createAndAddEdge(adjList, 2, 4); 57 | createAndAddEdge(adjList, 3, 3); 58 | createAndAddEdge(adjList, 4, 4); 59 | createAndAddEdge(adjList, 5, 5); 60 | ShortestPath(adjList, visitedVertex, source); // Find the shortest path from the source to all other vertices. 61 | //Shortest Path from 0: 0 1 2 3 3 2 62 | } // main() 63 | -------------------------------------------------------------------------------- /TopologicalSort.cpp: -------------------------------------------------------------------------------- 1 | // Author: Aakash Prabhu 2 | #include 3 | #include 4 | #include 5 | using namespace std; 6 | 7 | /* This program demonstrates the working of Topological Sort. 8 | * Topological Sort only works for a directed acyclic graph. 9 | * I have implemented this algorithm with the help of BFS. 10 | * Therefore, the overall time complexity is simply O(|V| + |E|) 11 | */ 12 | 13 | const int numVertices = 6; // 6 vertices (0,1,2,3,4,5) 14 | int source; 15 | vector visitedVertex(numVertices, false); // Mark everything as unvisited 16 | vector inDegree(numVertices, 0); // Initialize all in-Degrees to 0 17 | vector T; // This will store the vertices that TopologicalSort visits in order. 18 | void createAndAddEdge(vector adjList[], int u, int v){ 19 | adjList[u].push_back(v); 20 | } // To create adjacency list 21 | 22 | void TopologicalSort(vector adjList[]){ 23 | queue Q; //set up Queue for BFS 24 | int v; 25 | 26 | for (int i = 0; i < numVertices; i++) // for all vertices in the graph 27 | for (vector ::iterator it = adjList[i].begin(); it != adjList[i].end(); it++) // visit it's neighbors 28 | inDegree.at(*it)++; //increment inDegree of that child 29 | 30 | for (int i = 0; i < numVertices; i++) 31 | if (inDegree.at(i) == 0){ 32 | source = i; 33 | Q.push(source); // Push it onto the queue as a starting point for BFS 34 | visitedVertex.at(source) = true; // Mark it true 35 | break; 36 | } // Found a vertex with 0 inDegree -> This will be our source for Topological Sort 37 | 38 | while (!Q.empty()){ 39 | v = Q.front(); // Get v 40 | Q.pop(); 41 | T.push_back(v); // Add to T-Vector 42 | 43 | /* Now to proceed with Topological Sort, we remove the vertex and all its corresponding edges. 44 | * Which means, the in-degree's of all it's neighbors will be reduced by 1 45 | */ 46 | 47 | for (vector::iterator it = adjList[v].begin(); it != adjList[v].end(); it++) // Visit all neighbors 48 | if (!visitedVertex.at(*it)){ 49 | inDegree.at(*it)--; // Decrement inDegree of the neighbor, because its parent vertex has been removed 50 | if (inDegree.at(*it) == 0){ 51 | Q.push(*it); // Push the vertex with least inDegree -> New Source 52 | visitedVertex.at(*it) = true; // Mark it to be true 53 | } // Find new source 54 | } // if not visited 55 | } // While Queue is not empty 56 | } // TopologicalSort(vector adjList[]) 57 | 58 | int main (void){ 59 | vector adjList[numVertices]; // Create an array of vectors 60 | createAndAddEdge(adjList, 0, 1); 61 | createAndAddEdge(adjList, 0, 3); 62 | createAndAddEdge(adjList, 1, 2); 63 | createAndAddEdge(adjList, 1, 3); 64 | createAndAddEdge(adjList, 2, 3); 65 | createAndAddEdge(adjList, 2, 4); 66 | createAndAddEdge(adjList, 2, 5); 67 | createAndAddEdge(adjList, 3, 4); 68 | createAndAddEdge(adjList, 3, 5); 69 | createAndAddEdge(adjList, 4, 5); 70 | TopologicalSort(adjList); // Topological Sort for a given DAG 71 | cout << "Topological Sort for the given DAG: "; 72 | for (int i = 0; i < T.size(); i++) 73 | cout << T.at(i) << " "; 74 | cout << endl; 75 | //Should Print: 0 1 2 3 4 5 76 | 77 | } // main() 78 | -------------------------------------------------------------------------------- /images/DAG.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aakash1104/Graph-Algorithms/184f81e8cad08504b131ca313df8a42188b8ac2d/images/DAG.png -------------------------------------------------------------------------------- /images/connected-graph.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aakash1104/Graph-Algorithms/184f81e8cad08504b131ca313df8a42188b8ac2d/images/connected-graph.png -------------------------------------------------------------------------------- /images/directed-graph.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aakash1104/Graph-Algorithms/184f81e8cad08504b131ca313df8a42188b8ac2d/images/directed-graph.png -------------------------------------------------------------------------------- /images/simple-graph.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aakash1104/Graph-Algorithms/184f81e8cad08504b131ca313df8a42188b8ac2d/images/simple-graph.png -------------------------------------------------------------------------------- /images/strongly-connected.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aakash1104/Graph-Algorithms/184f81e8cad08504b131ca313df8a42188b8ac2d/images/strongly-connected.png -------------------------------------------------------------------------------- /images/undirected-graph.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aakash1104/Graph-Algorithms/184f81e8cad08504b131ca313df8a42188b8ac2d/images/undirected-graph.png -------------------------------------------------------------------------------- /kruskals.cpp: -------------------------------------------------------------------------------- 1 | // C++ program for Kruskal's algorithm to find Minimum 2 | // Spanning Tree of a given connected, undirected and 3 | // weighted graph 4 | #include 5 | using namespace std; 6 | 7 | // Creating shortcut for an integer pair 8 | 9 | 10 | // Structure to represent a graph 11 | struct Graph 12 | { 13 | int V, E; 14 | vector< pair> > edges; 15 | Graph(int V, int E) 16 | { 17 | this->V = V; 18 | this->E = E; 19 | } 20 | // Utility function to add an edge 21 | void addEdge(int u, int w, int v) 22 | { 23 | edges.push_back({w, {u, v}}); 24 | } 25 | int kruskalMST(); 26 | }; 27 | 28 | // To represent Disjoint Sets 29 | struct DisjointSets 30 | { 31 | int *parent, *rnk; 32 | int n; 33 | 34 | // Constructor. 35 | DisjointSets(int n) 36 | { 37 | // Allocate memory 38 | this->n = n; 39 | parent = new int[n+1]; 40 | rnk = new int[n+1]; 41 | for (int i = 0; i <= n; i++) 42 | { 43 | rnk[i] = 0; 44 | parent[i] = i; 45 | } 46 | } 47 | int find(int u) 48 | { 49 | if (u != parent[u]) 50 | parent[u] = find(parent[u]); 51 | return parent[u]; 52 | } 53 | 54 | // Union by rank 55 | void merge(int x, int y) 56 | { 57 | x = find(x), y = find(y); 58 | 59 | /* Make tree with smaller height 60 | a subtree of the other tree */ 61 | if (rnk[x] > rnk[y]) 62 | parent[y] = x; 63 | else // If rnk[x] <= rnk[y] 64 | parent[x] = y; 65 | 66 | if (rnk[x] == rnk[y]) 67 | rnk[y]++; 68 | } 69 | }; 70 | 71 | /* Functions returns weight of the MST*/ 72 | 73 | int Graph::kruskalMST() 74 | { 75 | int mst_wt = 0; // Initialize result 76 | 77 | // Sort edges in increasing order on basis of cost 78 | sort(edges.begin(), edges.end()); 79 | 80 | // Create disjoint sets 81 | DisjointSets ds(V); 82 | 83 | // Iterate through all sorted edges 84 | vector< pair> >::iterator it; 85 | for (it=edges.begin(); it!=edges.end(); it++) 86 | { 87 | int u = it->second.first; 88 | int v = it->second.second; 89 | 90 | int set_u = ds.find(u); 91 | int set_v = ds.find(v); 92 | 93 | // Check if the selected edge is creating 94 | // a cycle or not (Cycle is created if u 95 | // and v belong to same set) 96 | if (set_u != set_v) 97 | { 98 | cout << u << " - " << v << endl; 99 | mst_wt += it->first; 100 | ds.merge(set_u, set_v); 101 | } 102 | } 103 | 104 | return mst_wt; 105 | } 106 | 107 | // Driver program to test above functions 108 | int main() 109 | { 110 | /* Let us create above shown weighted 111 | and unidrected graph */ 112 | int V = 9, E = 14; 113 | Graph g(V, E); 114 | // making above shown graph 115 | g.addEdge(0, 5, 1); 116 | g.addEdge(0, 10, 3); 117 | g.addEdge(1, 2, 2); 118 | g.addEdge(1, 10, 5); 119 | g.addEdge(1, 5, 4); 120 | g.addEdge(2, 1, 3); 121 | g.addEdge(2, 5, 4); 122 | g.addEdge(2, 3, 0); 123 | g.addEdge(4, 2, 5); 124 | 125 | cout << "Edges of MST are \n"; 126 | int mst_wt = g.kruskalMST(); 127 | 128 | cout << "\nWeight of MST is " << mst_wt; 129 | 130 | return 0; 131 | } 132 | --------------------------------------------------------------------------------