diff --git a/include/Graph/Graph.hpp b/include/Graph/Graph.hpp index 1f438ad82..eee3478a4 100644 --- a/include/Graph/Graph.hpp +++ b/include/Graph/Graph.hpp @@ -1514,10 +1514,12 @@ const DijkstraResult Graph::dijkstra(const Node &source, // marking the distance of source as 0 dist[*source_node_it] = 0; + std::unordered_map parent; + parent[source.getUserId()] = ""; + while (!pq.empty()) { // second element of pair denotes the node / vertex shared> currentNode = pq.top().second; - // first element of pair denotes the distance double currentDist = pq.top().first; @@ -1541,6 +1543,7 @@ const DijkstraResult Graph::dijkstra(const Node &source, } else if (currentDist + dw_edge->getWeight() < dist[elem.first]) { dist[elem.first] = currentDist + dw_edge->getWeight(); pq.push(std::make_pair(dist[elem.first], elem.first)); + parent[elem.first.get()->getUserId()] = currentNode.get()->getUserId(); } } else if (elem.second->isDirected().has_value() && !elem.second->isDirected().value()) { @@ -1553,6 +1556,7 @@ const DijkstraResult Graph::dijkstra(const Node &source, } else if (currentDist + udw_edge->getWeight() < dist[elem.first]) { dist[elem.first] = currentDist + udw_edge->getWeight(); pq.push(std::make_pair(dist[elem.first], elem.first)); + parent[elem.first.get()->getUserId()] = currentNode.get()->getUserId(); } } else { // ERROR it shouldn't never returned ( does not exist a Node @@ -1572,6 +1576,13 @@ const DijkstraResult Graph::dijkstra(const Node &source, result.success = true; result.errorMessage = ""; result.result = dist[*target_node_it]; + std::string id = target.getUserId(); + while(parent[id] != ""){ + result.path.push_back(id); + id = parent[id]; + } + result.path.push_back(source.getUserId()); + std::reverse(result.path.begin(),result.path.end()); return result; } result.errorMessage = ERR_TARGET_NODE_NOT_REACHABLE; diff --git a/include/Utility/Typedef.hpp b/include/Utility/Typedef.hpp index bde8d523a..ba0046f4c 100755 --- a/include/Utility/Typedef.hpp +++ b/include/Utility/Typedef.hpp @@ -89,6 +89,7 @@ struct DijkstraResult_struct { false; // TRUE if the function does not return error, FALSE otherwise std::string errorMessage = ""; // message of error double result = INF_DOUBLE; // result (valid only if success is TRUE) + std::vector path; }; typedef DijkstraResult_struct DijkstraResult; diff --git a/test/DijkstraTest.cpp b/test/DijkstraTest.cpp index d7bcc1c3e..dc792eb54 100644 --- a/test/DijkstraTest.cpp +++ b/test/DijkstraTest.cpp @@ -29,9 +29,19 @@ TEST(DijkstraTest, correct_example_1) { CXXGraph::Graph graph(edgeSet); CXXGraph::DijkstraResult res = graph.dijkstra(node1, node3); + std::vector expected; + expected.push_back("1"); + expected.push_back("2"); + expected.push_back("3"); + int index=0; ASSERT_TRUE(res.success); ASSERT_EQ(res.errorMessage, ""); ASSERT_EQ(res.result, 2); + ASSERT_EQ(res.path.size(), expected.size()); + for(auto elem:res.path){ + ASSERT_EQ(elem,expected[index]); + index++; + } } TEST(DijkstraTest, correct_example_2) { @@ -52,9 +62,18 @@ TEST(DijkstraTest, correct_example_2) { CXXGraph::Graph graph(edgeSet); CXXGraph::DijkstraResult res = graph.dijkstra(node1, node3); + std::vector expected; + expected.push_back("1"); + expected.push_back("3"); + int index=0; ASSERT_TRUE(res.success); ASSERT_EQ(res.errorMessage, ""); ASSERT_EQ(res.result, 6); + ASSERT_EQ(res.path.size(), expected.size()); + for(auto elem:res.path){ + ASSERT_EQ(elem,expected[index]); + index++; + } } TEST(DijkstraTest, correct_example_3) { @@ -83,23 +102,62 @@ TEST(DijkstraTest, correct_example_3) { edgeSet.insert(make_shared>(edge6)); edgeSet.insert(make_shared>(edge7)); + std::vector expected; + expected.push_back("C"); + expected.push_back("A"); + expected.push_back("B"); + expected.push_back("E"); + int index=0; CXXGraph::Graph graph(edgeSet); CXXGraph::DijkstraResult res = graph.dijkstra(nodeC, nodeE); ASSERT_TRUE(res.success); ASSERT_EQ(res.errorMessage, ""); ASSERT_EQ(res.result, 5); + ASSERT_EQ(res.path.size(), expected.size()); + for(auto elem:res.path){ + ASSERT_EQ(elem,expected[index]); + index++; + } + expected.clear(); + expected.push_back("C"); + expected.push_back("A"); + index=0; res = graph.dijkstra(nodeC, nodeA); ASSERT_TRUE(res.success); ASSERT_EQ(res.errorMessage, ""); ASSERT_EQ(res.result, 1); + ASSERT_EQ(res.path.size(), expected.size()); + for(auto elem:res.path){ + ASSERT_EQ(elem,expected[index]); + index++; + } + expected.clear(); + expected.push_back("C"); + expected.push_back("A"); + expected.push_back("B"); + index=0; res = graph.dijkstra(nodeC, nodeB); ASSERT_TRUE(res.success); ASSERT_EQ(res.errorMessage, ""); ASSERT_EQ(res.result, 4); + ASSERT_EQ(res.path.size(), expected.size()); + for(auto elem:res.path){ + ASSERT_EQ(elem,expected[index]); + index++; + } + expected.clear(); + expected.push_back("C"); + expected.push_back("D"); + index=0; res = graph.dijkstra(nodeC, nodeD); ASSERT_TRUE(res.success); ASSERT_EQ(res.errorMessage, ""); ASSERT_EQ(res.result, 2); + ASSERT_EQ(res.path.size(), expected.size()); + for(auto elem:res.path){ + ASSERT_EQ(elem,expected[index]); + index++; + } } TEST(DijkstraTest, correct_example_4) { @@ -134,31 +192,94 @@ TEST(DijkstraTest, correct_example_4) { edgeSet.insert(make_shared>(edge8)); edgeSet.insert(make_shared>(edge9)); + std::vector expected; + expected.push_back("0"); + expected.push_back("1"); + int index=0; CXXGraph::Graph graph(edgeSet); CXXGraph::DijkstraResult res = graph.dijkstra(node0, node1); ASSERT_TRUE(res.success); ASSERT_EQ(res.errorMessage, ""); ASSERT_EQ(res.result, 2); + ASSERT_EQ(res.path.size(), expected.size()); + for(auto elem:res.path){ + ASSERT_EQ(elem,expected[index]); + index++; + } + expected.clear(); + expected.push_back("0"); + expected.push_back("2"); + index=0; + res = graph.dijkstra(node0, node2); ASSERT_TRUE(res.success); ASSERT_EQ(res.errorMessage, ""); ASSERT_EQ(res.result, 6); + ASSERT_EQ(res.path.size(), expected.size()); + for(auto elem:res.path){ + ASSERT_EQ(elem,expected[index]); + index++; + } + expected.clear(); + expected.push_back("0"); + expected.push_back("1"); + expected.push_back("3"); + index=0; res = graph.dijkstra(node0, node3); ASSERT_TRUE(res.success); ASSERT_EQ(res.errorMessage, ""); ASSERT_EQ(res.result, 7); + ASSERT_EQ(res.path.size(), expected.size()); + for(auto elem:res.path){ + ASSERT_EQ(elem,expected[index]); + index++; + } + expected.clear(); + expected.push_back("0"); + expected.push_back("1"); + expected.push_back("3"); + expected.push_back("4"); + index=0; res = graph.dijkstra(node0, node4); ASSERT_TRUE(res.success); ASSERT_EQ(res.errorMessage, ""); ASSERT_EQ(res.result, 17); + ASSERT_EQ(res.path.size(), expected.size()); + for(auto elem:res.path){ + ASSERT_EQ(elem,expected[index]); + index++; + } + expected.clear(); + expected.push_back("0"); + expected.push_back("1"); + expected.push_back("3"); + expected.push_back("5"); + index=0; res = graph.dijkstra(node0, node5); ASSERT_TRUE(res.success); ASSERT_EQ(res.errorMessage, ""); ASSERT_EQ(res.result, 22); + ASSERT_EQ(res.path.size(), expected.size()); + for(auto elem:res.path){ + ASSERT_EQ(elem,expected[index]); + index++; + } + expected.clear(); + expected.push_back("0"); + expected.push_back("1"); + expected.push_back("3"); + expected.push_back("4"); + expected.push_back("6"); + index=0; res = graph.dijkstra(node0, node6); ASSERT_TRUE(res.success); ASSERT_EQ(res.errorMessage, ""); ASSERT_EQ(res.result, 19); + ASSERT_EQ(res.path.size(), expected.size()); + for(auto elem:res.path){ + ASSERT_EQ(elem,expected[index]); + index++; + } } TEST(DijkstraTest, correct_example_5) { @@ -191,11 +312,22 @@ TEST(DijkstraTest, correct_example_5) { edgeSet.insert(make_shared>(edge8)); edgeSet.insert(make_shared>(edge9)); + std::vector expected; + int index=0; + expected.push_back("1"); + expected.push_back("3"); + expected.push_back("6"); + expected.push_back("5"); CXXGraph::Graph graph(edgeSet); CXXGraph::DijkstraResult res = graph.dijkstra(node1, node5); ASSERT_TRUE(res.success); ASSERT_EQ(res.errorMessage, ""); ASSERT_EQ(res.result, 20); + ASSERT_EQ(res.path.size(), expected.size()); + for(auto elem:res.path){ + ASSERT_EQ(elem,expected[index]); + index++; + } } TEST(DijkstraTest, non_weigthed_node_test) {