Skip to content

Commit d6f84a9

Browse files
authored
Merge pull request #54 from Debashis08/feature-graph-implementation
feature-test: kahn topo sort added
2 parents 3d0e95b + 24cdcf5 commit d6f84a9

File tree

4 files changed

+94
-1
lines changed

4 files changed

+94
-1
lines changed

Headers/0003_Graph/0003_TopologicalSort.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ namespace TopologicalSort
1717
int color;
1818
int discoveryTime;
1919
int finishingTime;
20+
int inDegree;
2021
Node* parent;
2122
Node(int value);
2223
};
@@ -35,6 +36,7 @@ namespace TopologicalSort
3536
void PushDirectedEdge(int valueU, int valueV);
3637
void PushSingleNode(int valueU);
3738
void TopologicalSort();
39+
void KahnTopologicalSort();
3840
vector<pair<int, pair<int, int>>> ShowTopologicalSortResult();
3941
};
4042
}

SourceCodes/0003_Graph/0003_TopologicalSort.cc

Lines changed: 51 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
#include "../Headers/0003_Graph/0003_TopologicalSort.h"
22
#include<vector>
3+
#include<queue>
34
#include<utility>
45
#include<climits>
56
#include<stdexcept>
@@ -10,9 +11,10 @@ namespace TopologicalSort
1011
Node::Node(int value)
1112
{
1213
this->data = value;
14+
this->color = WHITE;
1315
this->discoveryTime = INT_MAX;
1416
this->finishingTime = INT_MAX;
15-
this->color = WHITE;
17+
this->inDegree = 0;
1618
this->parent = nullptr;
1719
}
1820

@@ -61,6 +63,7 @@ namespace TopologicalSort
6163
Node* nodeV = this->MakeOrFindNode(valueV);
6264

6365
this->_adjlist[nodeU].push_back(nodeV);
66+
nodeV->inDegree++;
6467
}
6568

6669
void Graph::PushSingleNode(int valueU)
@@ -84,6 +87,53 @@ namespace TopologicalSort
8487
}
8588
}
8689

90+
void Graph::KahnTopologicalSort()
91+
{
92+
// Step-1 Compute in-degree of each vertices
93+
// This is already done while creating the graph
94+
this->time = 0;
95+
queue<Node*> nodeQueue;
96+
97+
// Step-2 Enqueue vertices with in-degree 0
98+
for (auto& node : this->_nodeMap)
99+
{
100+
if (node.second->inDegree == 0)
101+
{
102+
this->time++;
103+
node.second->discoveryTime = time;
104+
nodeQueue.push(node.second);
105+
}
106+
}
107+
108+
// Step-3 Process vertices in queue
109+
while (!nodeQueue.empty())
110+
{
111+
Node* node = nodeQueue.front();
112+
nodeQueue.pop();
113+
this->time++;
114+
node->finishingTime = time;
115+
this->_topologicalSortedNodeList.push_back(node);
116+
117+
// Step-4 Process all the neighbours of current node based on in-degree
118+
for (auto& neighbour : this->_adjlist[node])
119+
{
120+
neighbour->inDegree--;
121+
if (neighbour->inDegree == 0)
122+
{
123+
this->time++;
124+
neighbour->discoveryTime = time;
125+
nodeQueue.push(neighbour);
126+
}
127+
}
128+
}
129+
130+
// Step-5 Check if a cycle exists
131+
if (this->_topologicalSortedNodeList.size() != this->_nodeMap.size())
132+
{
133+
this->hasCycle = true;
134+
}
135+
}
136+
87137
vector<pair<int, pair<int, int>>> Graph::ShowTopologicalSortResult()
88138
{
89139
if (this->hasCycle == true)

SourceCodes/0003_Graph/0014_AllPairsShortestPathsJohnson.cc

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,8 +141,12 @@ namespace AllPairsShortestPathsJohnson
141141
// Creating the graph G'
142142
this->_augmentedAdjlist = this->_adjlist;
143143
this->_augmentedEdgeList = this->_edgeList;
144+
145+
// Source Node s
144146
Node* source = new Node(0);
145147
this->_nodeMap[0] = source;
148+
149+
// Creating all the augmented edges in G'.E = G.E U {(s, v) : v in G.V
146150
for (auto& node : this->_nodeMap)
147151
{
148152
if (node.second != source)

Tests/0003_Graph/0003_TopologicalSortTest.cc

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,4 +104,41 @@ namespace TopologicalSort
104104
// Expected output if cycle detection is implemented
105105
EXPECT_THROW(graph.ShowTopologicalSortResult(), runtime_error);
106106
}
107+
108+
TEST(TopoSortTesting, ShowTopoSortResultUsingKahnAlgorithm)
109+
{
110+
Graph graph;
111+
112+
graph.PushDirectedEdge(1, 2);
113+
graph.PushDirectedEdge(1, 4);
114+
graph.PushDirectedEdge(2, 3);
115+
graph.PushDirectedEdge(4, 3);
116+
graph.PushSingleNode(5);
117+
graph.PushDirectedEdge(6, 7);
118+
graph.PushDirectedEdge(6, 8);
119+
graph.PushDirectedEdge(7, 4);
120+
graph.PushDirectedEdge(7, 8);
121+
graph.PushDirectedEdge(9, 8);
122+
123+
graph.KahnTopologicalSort();
124+
125+
string actualResult = unitTestHelper.SerializeVectorToString(graph.ShowTopologicalSortResult());
126+
string expectedResult = "1(1,5) 5(2,7) 6(3,8) 9(4,10) 2(6,11) 7(9,12) 4(13,15) 8(14,17) 3(16,18)";
127+
128+
EXPECT_EQ(actualResult, expectedResult);
129+
}
130+
131+
// Test with a cyclic graph to verify it can detect cycles
132+
TEST(TopoSortTesting, CyclicGraphUsingKahnAlgorithm)
133+
{
134+
Graph graph;
135+
graph.PushDirectedEdge(1, 2);
136+
graph.PushDirectedEdge(2, 3);
137+
graph.PushDirectedEdge(3, 1); // Cycle: 1 -> 2 -> 3 -> 1
138+
139+
graph.KahnTopologicalSort();
140+
141+
// Expected output if cycle detection is implemented
142+
EXPECT_THROW(graph.ShowTopologicalSortResult(), runtime_error);
143+
}
107144
}

0 commit comments

Comments
 (0)