TheAlgorithms/C++
1.0.0
All the algorithms implemented in C++
Toggle main menu visibility
Loading...
Searching...
No Matches
cycle_check_directed_graph.cpp
1
9
10
#include <cstdint>
11
#include <iostream>
// for std::cout
12
#include <map>
// for std::map
13
#include <queue>
// for std::queue
14
#include <stdexcept>
// for throwing errors
15
#include <type_traits>
// for std::remove_reference
16
#include <utility>
// for std::move
17
#include <vector>
// for std::vector
18
25
struct
Edge
{
26
unsigned
int
src;
27
unsigned
int
dest;
28
29
Edge() =
delete
;
30
~Edge() =
default
;
31
Edge(Edge&&) =
default
;
32
Edge& operator=(Edge&&) =
default
;
33
Edge(Edge
const
&) =
default
;
34
Edge& operator=(Edge
const
&) =
default
;
35
41
Edge
(
unsigned
int
source,
unsigned
int
destination)
42
: src(source), dest(destination) {}
43
};
44
45
using
AdjList = std::map<unsigned int, std::vector<unsigned int>>;
46
55
class
Graph
{
56
public
:
57
Graph() : m_adjList({}) {}
58
~Graph() =
default
;
59
Graph(Graph&&) =
default
;
60
Graph& operator=(Graph&&) =
default
;
61
Graph(Graph
const
&) =
default
;
62
Graph& operator=(Graph
const
&) =
default
;
63
69
Graph
(
unsigned
int
vertices, AdjList adjList)
70
: m_vertices(vertices), m_adjList(std::move(adjList)) {}
71
77
Graph
(
unsigned
int
vertices, AdjList&& adjList)
78
: m_vertices(vertices), m_adjList(std::move(adjList)) {}
79
89
Graph
(
unsigned
int
vertices, std::vector<Edge>
const
& edges)
90
: m_vertices(vertices) {
91
for
(
auto
const
& edge : edges) {
92
if
(edge.src >= vertices || edge.dest >= vertices) {
93
throw
std::range_error(
94
"Either src or dest of edge out of range"
);
95
}
96
m_adjList[edge.src].emplace_back(edge.dest);
97
}
98
}
99
104
std::remove_reference<AdjList>::type
const
&
getAdjList
()
const
{
105
return
m_adjList;
106
}
107
111
unsigned
int
getVertices
()
const
{
return
m_vertices; }
112
119
void
addVertices
(
unsigned
int
num = 1) { m_vertices += num; }
120
125
void
addEdge
(
Edge
const
& edge) {
126
if
(edge.src >= m_vertices || edge.dest >= m_vertices) {
127
throw
std::range_error(
"Either src or dest of edge out of range"
);
128
}
129
m_adjList[edge.src].emplace_back(edge.dest);
130
}
131
137
void
addEdge
(
unsigned
int
source,
unsigned
int
destination) {
138
if
(source >= m_vertices || destination >= m_vertices) {
139
throw
std::range_error(
140
"Either source or destination of edge out of range"
);
141
}
142
m_adjList[source].emplace_back(destination);
143
}
144
145
private
:
146
unsigned
int
m_vertices = 0;
147
AdjList m_adjList;
148
};
149
159
class
CycleCheck
{
160
private
:
161
enum
nodeStates : uint8_t { not_visited = 0, in_stack, visited };
162
171
static
bool
isCyclicDFSHelper
(AdjList
const
& adjList,
172
std::vector<nodeStates>* state,
173
unsigned
int
node
) {
174
// Add node "in_stack" state.
175
(*state)[
node
] = in_stack;
176
177
// If the node has children, then recursively visit all children of the
178
// node.
179
auto
const
it = adjList.find(
node
);
180
if
(it != adjList.end()) {
181
for
(
auto
child : it->second) {
182
// If state of child node is "not_visited", evaluate that child
183
// for presence of cycle.
184
auto
state_of_child = (*state)[child];
185
if
(state_of_child == not_visited) {
186
if
(
isCyclicDFSHelper
(adjList, state, child)) {
187
return
true
;
188
}
189
}
else
if
(state_of_child == in_stack) {
190
// If child node was "in_stack", then that means that there
191
// is a cycle in the graph. Return true for presence of the
192
// cycle.
193
return
true
;
194
}
195
}
196
}
197
198
// Current node has been evaluated for the presence of cycle and had no
199
// cycle. Mark current node as "visited".
200
(*state)[
node
] = visited;
201
// Return that current node didn't result in any cycles.
202
return
false
;
203
}
204
205
public
:
213
static
bool
isCyclicDFS
(
Graph
const
&
graph
) {
214
auto
vertices =
graph
.getVertices();
215
223
std::vector<nodeStates> state(vertices, not_visited);
224
225
// Start visiting each node.
226
for
(
unsigned
int
node
= 0;
node
< vertices;
node
++) {
227
// If a node is not visited, only then check for presence of cycle.
228
// There is no need to check for presence of cycle for a visited
229
// node as it has already been checked for presence of cycle.
230
if
(state[
node
] == not_visited) {
231
// Check for cycle.
232
if
(
isCyclicDFSHelper
(
graph
.getAdjList(), &state,
node
)) {
233
return
true
;
234
}
235
}
236
}
237
238
// All nodes have been safely traversed, that means there is no cycle in
239
// the graph. Return false.
240
return
false
;
241
}
242
250
static
bool
isCyclicBFS
(
Graph
const
&
graph
) {
251
auto
graphAjdList =
graph
.getAdjList();
252
auto
vertices =
graph
.getVertices();
253
254
std::vector<unsigned int> indegree(vertices, 0);
255
// Calculate the indegree i.e. the number of incident edges to the node.
256
for
(
auto
const
&
list
: graphAjdList) {
257
auto
children =
list
.second;
258
for
(
auto
const
& child : children) {
259
indegree[child]++;
260
}
261
}
262
263
std::queue<unsigned int> can_be_solved;
264
for
(
unsigned
int
node
= 0;
node
< vertices;
node
++) {
265
// If a node doesn't have any input edges, then that node will
266
// definately not result in a cycle and can be visited safely.
267
if
(!indegree[
node
]) {
268
can_be_solved.emplace(
node
);
269
}
270
}
271
272
// Vertices that need to be traversed.
273
auto
remain = vertices;
274
// While there are safe nodes that we can visit.
275
while
(!can_be_solved.empty()) {
276
auto
solved = can_be_solved.front();
277
// Visit the node.
278
can_be_solved.pop();
279
// Decrease number of nodes that need to be traversed.
280
remain--;
281
282
// Visit all the children of the visited node.
283
auto
it = graphAjdList.find(solved);
284
if
(it != graphAjdList.end()) {
285
for
(
auto
child : it->second) {
286
// Check if we can visited the node safely.
287
if
(--indegree[child] == 0) {
288
// if node can be visited safely, then add that node to
289
// the visit queue.
290
can_be_solved.emplace(child);
291
}
292
}
293
}
294
}
295
296
// If there are still nodes that we can't visit, then it means that
297
// there is a cycle and return true, else return false.
298
return
!(remain == 0);
299
}
300
};
301
305
int
main
() {
306
// Instantiate the graph.
307
Graph
g
(7, std::vector<Edge>{{0, 1}, {1, 2}, {2, 0}, {2, 5}, {3, 5}});
308
// Check for cycle using BFS method.
309
std::cout <<
CycleCheck::isCyclicBFS
(g) <<
'\n'
;
310
311
// Check for cycle using DFS method.
312
std::cout <<
CycleCheck::isCyclicDFS
(g) <<
'\n'
;
313
return
0;
314
}
CycleCheck
Definition
cycle_check_directed_graph.cpp:159
CycleCheck::isCyclicDFSHelper
static bool isCyclicDFSHelper(AdjList const &adjList, std::vector< nodeStates > *state, unsigned int node)
Definition
cycle_check_directed_graph.cpp:171
CycleCheck::isCyclicBFS
static bool isCyclicBFS(Graph const &graph)
Definition
cycle_check_directed_graph.cpp:250
CycleCheck::isCyclicDFS
static bool isCyclicDFS(Graph const &graph)
Definition
cycle_check_directed_graph.cpp:213
Edge
Definition
bellman_ford.cpp:8
Edge::Edge
Edge(unsigned int source, unsigned int destination)
Definition
cycle_check_directed_graph.cpp:41
Graph
Definition
bellman_ford.cpp:14
Graph::getAdjList
std::remove_reference< AdjList >::type const & getAdjList() const
Definition
cycle_check_directed_graph.cpp:104
Graph::Graph
Graph(unsigned int vertices, AdjList &&adjList)
Definition
cycle_check_directed_graph.cpp:77
Graph::getVertices
unsigned int getVertices() const
Definition
cycle_check_directed_graph.cpp:111
Graph::Graph
Graph(unsigned int vertices, std::vector< Edge > const &edges)
Definition
cycle_check_directed_graph.cpp:89
Graph::addVertices
void addVertices(unsigned int num=1)
Definition
cycle_check_directed_graph.cpp:119
Graph::addEdge
void addEdge(unsigned int source, unsigned int destination)
Definition
cycle_check_directed_graph.cpp:137
Graph::Graph
Graph(unsigned int vertices, AdjList adjList)
Definition
cycle_check_directed_graph.cpp:69
Graph::addEdge
void addEdge(Edge const &edge)
Definition
cycle_check_directed_graph.cpp:125
numerical_methods::simpson_method::g
double g(double x)
Another test function.
Definition
composite_simpson_rule.cpp:115
main
int main()
Main function.
Definition
generate_parentheses.cpp:110
graph
Graph Algorithms.
list
Definition
hash_search.cpp:29
node
Definition
binary_search_tree.cpp:11
graph
cycle_check_directed_graph.cpp
Generated by
1.18.0