diff --git a/Headers/0003_Graph/0003_TopologicalSort.h b/Headers/0003_Graph/0003_TopologicalSort.h index 88cc7b3..b4dd489 100644 --- a/Headers/0003_Graph/0003_TopologicalSort.h +++ b/Headers/0003_Graph/0003_TopologicalSort.h @@ -22,6 +22,7 @@ class TopologicalSortGraph { private: int time; + bool hasCycle; map> _adjlist; map _nodeMap; TopologicalSortNode* MakeOrFindNode(int value); @@ -29,6 +30,7 @@ class TopologicalSortGraph void DepthFirstSearch(TopologicalSortNode* DFSNode); public: void PushDirectedEdge(int valueU, int valueV); + void PushSingleNode(int valueU); void TopologicalSort(); vector>> ShowTopologicalSortResult(); }; \ No newline at end of file diff --git a/SourceCodes/0003_Graph/0003_TopologicalSort.cc b/SourceCodes/0003_Graph/0003_TopologicalSort.cc index 3c8d039..c98925e 100644 --- a/SourceCodes/0003_Graph/0003_TopologicalSort.cc +++ b/SourceCodes/0003_Graph/0003_TopologicalSort.cc @@ -2,6 +2,7 @@ #include #include #include +#include using namespace std; TopologicalSortNode::TopologicalSortNode(int value) @@ -40,6 +41,11 @@ void TopologicalSortGraph::DepthFirstSearch(TopologicalSortNode* nodeU) nodeV->parent = nodeU; this->DepthFirstSearch(nodeV); } + else if (nodeV->color == GRAY) + { + this->hasCycle = true; + return; + } } nodeU->color = BLACK; this->time++; @@ -55,6 +61,11 @@ void TopologicalSortGraph::PushDirectedEdge(int valueU, int valueV) this->_adjlist[nodeU].push_back(nodeV); } +void TopologicalSortGraph::PushSingleNode(int valueU) +{ + TopologicalSortNode* nodeU = this->MakeOrFindNode(valueU); +} + void TopologicalSortGraph::TopologicalSort() { this->time = 0; @@ -63,12 +74,20 @@ void TopologicalSortGraph::TopologicalSort() if (iterator.second->color == WHITE) { this->DepthFirstSearch(iterator.second); + if (this->hasCycle == true) + { + break; + } } } } vector>> TopologicalSortGraph::ShowTopologicalSortResult() { + if (this->hasCycle == true) + { + throw runtime_error("Cycle Detected"); + } vector>> result; for (auto& node : this->_topologicalSortedNodeList) { diff --git a/Tests/0003_Graph/0003_TopologicalSortTest.cc b/Tests/0003_Graph/0003_TopologicalSortTest.cc index e69de29..4eea735 100644 --- a/Tests/0003_Graph/0003_TopologicalSortTest.cc +++ b/Tests/0003_Graph/0003_TopologicalSortTest.cc @@ -0,0 +1,107 @@ +#include +#include "../Headers/0003_Graph/0003_TopologicalSort.h" +#include "../0000_CommonUtilities/UnitTestHelper.h" + +namespace TopologicalSortTest +{ + UnitTestHelper unitTestHelper; + + TEST(TopoSortTesting, ShowTopoSortResult) + { + TopologicalSortGraph graph; + + graph.PushDirectedEdge(1, 2); + graph.PushDirectedEdge(1, 4); + graph.PushDirectedEdge(2, 3); + graph.PushDirectedEdge(4, 3); + graph.PushSingleNode(5); + graph.PushDirectedEdge(6, 7); + graph.PushDirectedEdge(6, 8); + graph.PushDirectedEdge(7, 4); + graph.PushDirectedEdge(7, 8); + graph.PushDirectedEdge(9, 8); + + graph.TopologicalSort(); + + string actualResult = unitTestHelper.VerifyVectorResult(graph.ShowTopologicalSortResult()); + string expectedResult = "9(17,18) 6(11,16) 7(12,15) 8(13,14) 5(9,10) 1(1,8) 4(6,7) 2(2,5) 3(3,4)"; + + EXPECT_EQ(actualResult, expectedResult); + } + + // Test with a larger graph and multiple paths between nodes + TEST(TopoSortTesting, LargeGraphMultiplePaths) + { + TopologicalSortGraph graph; + graph.PushDirectedEdge(1, 2); + graph.PushDirectedEdge(1, 3); + graph.PushDirectedEdge(2, 4); + graph.PushDirectedEdge(3, 4); + graph.PushDirectedEdge(4, 5); + graph.PushDirectedEdge(5, 6); + graph.PushDirectedEdge(6, 7); + + graph.TopologicalSort(); + string actualResult = unitTestHelper.VerifyVectorResult(graph.ShowTopologicalSortResult()); + string expectedResult = "1(1,14) 3(12,13) 2(2,11) 4(3,10) 5(4,9) 6(5,8) 7(6,7)"; + + EXPECT_EQ(actualResult, expectedResult); + } + + // Test with a graph containing disconnected components + TEST(TopoSortTesting, DisconnectedGraph) + { + TopologicalSortGraph graph; + graph.PushDirectedEdge(1, 2); + graph.PushDirectedEdge(3, 4); + graph.PushDirectedEdge(5, 6); + + graph.TopologicalSort(); + string actualResult = unitTestHelper.VerifyVectorResult(graph.ShowTopologicalSortResult()); + string expectedResult = "5(9,12) 6(10,11) 3(5,8) 4(6,7) 1(1,4) 2(2,3)"; + + EXPECT_EQ(actualResult, expectedResult); + } + + // Test with a graph that has multiple nodes pointing to the same node + TEST(TopoSortTesting, MultipleIncomingEdges) + { + TopologicalSortGraph graph; + graph.PushDirectedEdge(1, 3); + graph.PushDirectedEdge(2, 3); + graph.PushDirectedEdge(3, 4); + + graph.TopologicalSort(); + string actualResult = unitTestHelper.VerifyVectorResult(graph.ShowTopologicalSortResult()); + string expectedResult = "2(7,8) 1(1,6) 3(2,5) 4(3,4)"; + + EXPECT_EQ(actualResult, expectedResult); + } + + // Test for a single-node graph to check the base case + TEST(TopoSortTesting, SingleNodeGraph) + { + TopologicalSortGraph graph; + graph.PushSingleNode(1); + + graph.TopologicalSort(); + string actualResult = unitTestHelper.VerifyVectorResult(graph.ShowTopologicalSortResult()); + string expectedResult = "1(1,2)"; + + EXPECT_EQ(actualResult, expectedResult); + } + + // Test with a cyclic graph to verify it can detect cycles (assuming cycle detection is implemented) + TEST(TopoSortTesting, CyclicGraph) + { + TopologicalSortGraph graph; + graph.PushDirectedEdge(1, 2); + graph.PushDirectedEdge(2, 3); + graph.PushDirectedEdge(3, 1); // Cycle: 1 -> 2 -> 3 -> 1 + + graph.TopologicalSort(); + + // Expected output if cycle detection is implemented + EXPECT_THROW(graph.ShowTopologicalSortResult(), runtime_error); + } +} \ No newline at end of file