Skip to content

Commit de23155

Browse files
committed
Add implementations of:
* Graph representations * Traversal algorithms * Algos for detecting cycle * Topological Sorting algo * An MST algo (Prim's)
0 parents  commit de23155

File tree

10 files changed

+760
-0
lines changed

10 files changed

+760
-0
lines changed

Detect_Cycle/directed.cc

+86
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
/** Given a directed graph, check whether the graph contains a cycle or not.
2+
*
3+
* Note: There is a cycle in a graph only if there is a back edge present in
4+
* it. A back edge is an edge that is from a node to itself (self-loop) or
5+
* one of its ancestor i.e. an edge to the next node will form a cycle, only
6+
* if that node is an ancestor of the present node.
7+
*
8+
* To detect a back edge, we can keep track of vertices currently in recursion
9+
* stack of function for DFS traversal. If we reach a vertex that is already in
10+
* the recursion stack, then there is a cycle in the tree.
11+
*/
12+
#include <bits/stdc++.h>
13+
using namespace std;
14+
15+
class graph {
16+
int nv;
17+
vector<list<int>> adj;
18+
// A utility function to be used by main "cyclic" function
19+
bool util(int s, vector<bool>& visited, vector<bool>& recur_stack);
20+
21+
public:
22+
graph(int num) : nv(num), adj(num) {}
23+
void addEdge(int u, int v) {
24+
adj[u].push_back(v);
25+
}
26+
bool cyclic();
27+
};
28+
29+
bool graph::util(int s, vector<bool>& visited, vector<bool>& recur_stack) {
30+
if (visited[s] == false) {
31+
32+
// Mark the current vertex visited and a part of recur_stack.
33+
visited[s] = true;
34+
recur_stack[s] = true;
35+
36+
// Recur through all the adjacent vertices to the current vertex
37+
for (auto i = adj[s].begin(); i != adj[s].end(); ++i) {
38+
// If an adjacent has not been visited then recur for it.
39+
if (!visited[*i]) {
40+
if (util(*i, visited, recur_stack))
41+
return true;
42+
}
43+
// If an adjacent has been visited and is present in the
44+
// recur_stack then it forms a cycle in the graph.
45+
else if (recur_stack[*i])
46+
return true;
47+
}
48+
}
49+
// Set the current vertex as false in recur_stack
50+
// to mark it as removed from it.
51+
recur_stack[s] = false;
52+
53+
return false;
54+
}
55+
56+
bool graph::cyclic() {
57+
// Mark all vertices as not visited.
58+
vector<bool> visited(nv, false);
59+
vector<bool> recur_stack(nv, false);
60+
61+
// Call Util for each vertex.
62+
for (int i = 0; i < nv; i++) {
63+
// Returns true if a cycle is present in the graph.
64+
if (util(i, visited, recur_stack))
65+
return true;
66+
}
67+
return false;
68+
}
69+
70+
int main() {
71+
graph g(4);
72+
73+
g.addEdge(0, 1);
74+
g.addEdge(0, 2);
75+
g.addEdge(1, 3);
76+
g.addEdge(2, 3);
77+
g.addEdge(3, 1);
78+
79+
if (g.cyclic())
80+
cout << "Graph is cyclic.\n";
81+
else
82+
cout << "Not a cyclic graph.\n";
83+
84+
return 0;
85+
}
86+
// Time Complexity: Same as DFS i.e. O(V + E).

Detect_Cycle/directed_color.cc

+75
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
/** Given a directed graph, check whether the graph contains a cycle or not.
2+
*
3+
* Note: The idea is to do DFS of given graph and while doing traversal, assign
4+
* one of the three colors (white, gray, black) to every vertex.
5+
*/
6+
#include <bits/stdc++.h>
7+
using namespace std;
8+
9+
enum COLOR {WHITE, GRAY, BLACK};
10+
11+
class graph {
12+
int nv;
13+
vector<list<int>> adj;
14+
// A utility function to be used by main "cyclic" function
15+
bool util(int s, vector<int>& color);
16+
public:
17+
graph(int num) : nv(num), adj(num) {}
18+
void addEdge(int u, int v) {
19+
adj[u].push_back(v);
20+
}
21+
bool cyclic();
22+
};
23+
24+
bool graph::util(int s, vector<int>& visited) {
25+
if (visited[s] == false) {
26+
27+
visited[s] = GRAY;
28+
29+
// Recur through all the adjacent vertices to the current vertex
30+
for (auto i = adj[s].begin(); i != adj[s].end(); ++i) {
31+
// If the current vertex has not been processed and there is
32+
// a back edge in subtree rooted at it.
33+
if (visited[*i] == WHITE && util(*i, visited))
34+
return true;
35+
if (visited[*i] == GRAY)
36+
return true;
37+
}
38+
}
39+
// Mark the vertex as fully processed.
40+
visited[s] = BLACK;
41+
42+
return false;
43+
}
44+
45+
bool graph::cyclic() {
46+
// Mark all vertices as not visited.
47+
vector<int> color(nv, WHITE);
48+
49+
// Call Util for each vertex.
50+
for (int i = 0; i < nv; i++) {
51+
// Returns true if a cycle is present in the graph.
52+
if (util(i, color))
53+
return true;
54+
}
55+
56+
return false;
57+
}
58+
59+
int main() {
60+
graph g(4);
61+
62+
g.addEdge(0, 1);
63+
g.addEdge(0, 2);
64+
g.addEdge(1, 3);
65+
g.addEdge(2, 3);
66+
g.addEdge(3, 1);
67+
68+
if (g.cyclic())
69+
cout << "Graph is cyclic.\n";
70+
else
71+
cout << "Not a cyclic graph.\n";
72+
73+
return 0;
74+
}
75+
// Time Complexity: Same as DFS i.e. O(V + E).

Detect_Cycle/undirected.cc

+77
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
/** Given a undirected graph, check whether the graph contains a cycle or not.
2+
*
3+
* Note: Like directed graphs, we can use DFS to detect cycle in an undirected graph.
4+
* For every visited vertex ‘v’, if there is an adjacent ‘u’ such that u has
5+
* already been visited and u is not parent of v, then there is a cycle in graph.
6+
*
7+
* The assumption of this approach is that there are no parallel edges between any
8+
* two vertices.
9+
*/
10+
#include <bits/stdc++.h>
11+
using namespace std;
12+
13+
class graph {
14+
int nv;
15+
vector<list<int>> adj;
16+
// A utility function to be used by main "cyclic" function
17+
bool util(int s, vector<bool>& visited, int parent);
18+
public:
19+
graph(int num) : nv(num), adj(num) {}
20+
void addEdge(int u, int v) {
21+
// Birectional edges
22+
adj[u].push_back(v);
23+
adj[v].push_back(u);
24+
}
25+
bool cyclic();
26+
};
27+
28+
bool graph::util(int s, vector<bool>& visited, int parent) {
29+
visited[s] = true;
30+
31+
// Recur through all the adjacent vertices to the current vertex
32+
for (auto i = adj[s].begin(); i != adj[s].end(); ++i) {
33+
// If an adjacent vertex has not been visited then recur for it.
34+
if (!visited[*i]) {
35+
if(util(*i, visited, s))
36+
return true;
37+
}
38+
39+
// If an adjacent has been visited and it's not the parent
40+
// then it forms a cycle in the graph.
41+
else if (*i != parent)
42+
return true;
43+
}
44+
return false;
45+
}
46+
47+
bool graph::cyclic() {
48+
// Mark all vertices as not visited.
49+
vector<bool> visited(nv, false);
50+
51+
// Call Util for each vertex.
52+
for (int i = 0; i < nv; i++) {
53+
// Recur only if i has not been visited.
54+
if (!visited[i]) {
55+
if (util(i, visited, -1))
56+
return true;
57+
}
58+
}
59+
return false;
60+
}
61+
62+
int main() {
63+
graph g(4);
64+
65+
g.addEdge(0, 1);
66+
g.addEdge(0, 2);
67+
g.addEdge(1, 3);
68+
g.addEdge(2, 3);
69+
70+
if (g.cyclic())
71+
cout << "Graph is cyclic.\n";
72+
else
73+
cout << "Not a cyclic graph.\n";
74+
75+
return 0;
76+
}
77+
// Time Complexity: Same as DFS i.e. O(V + E).

Min_Spanning_Tree/prim_list.cc

+85
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
/** Given an undirected, connected and weighted graph, find MST of the graphs
2+
* using Prim’s algorithm.
3+
*/
4+
#include <bits/stdc++.h>
5+
using namespace std;
6+
7+
typedef pair<int, int> int_pair;
8+
9+
class graph {
10+
int nv;
11+
// A weighted graph, so need to store a vertex and
12+
// weight pair for every single vertex.
13+
vector<vector<int_pair>> adj;
14+
15+
public:
16+
graph(int num) : nv(num), adj(num) {}
17+
void addEdge(int u, int v, int wt) {
18+
adj[u].push_back(make_pair(v, wt));
19+
adj[v].push_back(make_pair(u, wt));
20+
}
21+
void prims(int s);
22+
void print_mst();
23+
};
24+
25+
void graph::prims(int s) {
26+
// Create a min-heap using priority_queue container. priority_queue
27+
// container class provides a constructor that requires two extra
28+
// arguments to make it a min heap i.e. vector<...> & greater<...>.
29+
priority_queue<int_pair, vector<int_pair>, greater<int_pair>> heap;
30+
31+
// A vector for weight and initialise as INT_MAX.
32+
vector<int> weight(nv, INT_MAX);
33+
34+
// Another vector to store the parent of vertices.
35+
vector<int> parent(nv, -1);
36+
37+
// A vector to keep track of vertices included in MST.
38+
vector<bool> mst(nv, false);
39+
40+
// Set weight of source vertex as zero.
41+
weight[s] = 0;
42+
// Insert source vertex in the heap.
43+
heap.push(make_pair(weight[s], s));
44+
45+
while (!heap.empty()) {
46+
// Extract the min vertex based on their associated weights.
47+
int u = heap.top().second;
48+
heap.pop();
49+
50+
// Include extracted vertex in mst.
51+
mst[u] = true;
52+
vector<pair<int, int>>::iterator i;
53+
for (i = adj[u].begin(); i != adj[u].end(); ++i) {
54+
// Get the vertex label and the weight
55+
int v = (*i).first;
56+
int v_wt = (*i).second;
57+
58+
// If v is not in mst and edge (u, v) weight < weight of v
59+
if (mst[v] == false && v_wt < weight[v]) {
60+
// Update weight of v
61+
weight[v] = v_wt;
62+
heap.push(make_pair(weight[v], v));
63+
parent[v] = u;
64+
}
65+
}
66+
}
67+
for (int i = 1; i < nv; i++)
68+
cout << parent[i] << " -> " << i << endl;
69+
cout << endl;
70+
}
71+
72+
73+
int main() {
74+
graph g(5);
75+
76+
g.addEdge(0, 1, 1);
77+
g.addEdge(0, 2, 3);
78+
g.addEdge(1, 2, 7);
79+
g.addEdge(2, 3, 4);
80+
g.addEdge(3, 4, 6);
81+
82+
g.prims(0);
83+
84+
return 0;
85+
}

0 commit comments

Comments
 (0)