diff --git a/alib2data/src/graph/directed/AdjacencyMatrixDirectedGraph.cpp b/alib2data/src/graph/directed/AdjacencyMatrixDirectedGraph.cpp index e27b23436719e0a894375be1f197cc8b2f700a55..6bcdb3dc426f2884ec45e69253a1c98aa22a4cb9 100644 --- a/alib2data/src/graph/directed/AdjacencyMatrixDirectedGraph.cpp +++ b/alib2data/src/graph/directed/AdjacencyMatrixDirectedGraph.cpp @@ -51,7 +51,7 @@ std::set<Node> AdjacencyMatrixDirectedGraph::neighbors(const Node &node) const } for (auto i : search->second) { - if (i.second) { + if (i.second > 0) { out.insert(i.first); } } @@ -115,7 +115,7 @@ bool AdjacencyMatrixDirectedGraph::addEdge(const DirectedEdge &edge) edges.insert(edge); - adj[edge.getFromNode()].insert({edge.getToNode(), true}); + adj[edge.getFromNode()][edge.getToNode()]++; return true; } @@ -129,9 +129,9 @@ bool AdjacencyMatrixDirectedGraph::removeEdge(const DirectedEdge &edge) edges.erase(search); - // Don't touch adj if there still is an edge, in case of multigraph - if (findEdges(edge.getFromNode(), edge.getToNode()).empty()) { - auto &map = adj[edge.getFromNode()]; + auto &map = adj[edge.getFromNode()]; + int &val = map[edge.getToNode()]; + if (--val <= 0) { map.erase(edge.getToNode()); if (map.empty()) { adj.erase(edge.getFromNode()); diff --git a/alib2data/src/graph/directed/AdjacencyMatrixDirectedGraph.h b/alib2data/src/graph/directed/AdjacencyMatrixDirectedGraph.h index a3f9915d0c3ed89ece71e7825be4df297a056f43..5dc9aa4adce0a08d65bcc78f90ae8fa342f3549b 100644 --- a/alib2data/src/graph/directed/AdjacencyMatrixDirectedGraph.h +++ b/alib2data/src/graph/directed/AdjacencyMatrixDirectedGraph.h @@ -14,18 +14,17 @@ namespace graph { * * unordered_map: * [ -- ][ n1 ][ n2 ][ n3 ][ n4 ] - * [ n1 ] - x - x - * [ n2 ] x - - x - * [ n3 ] - - - x - * [ n4 ] x - x - + * [ n1 ] 0 2 0 1 + * [ n2 ] 1 0 0 1 + * [ n3 ] 0 0 0 1 + * [ n4 ] 1 0 1 0 * * edges: - * n1 -> n2, n1 -> n4 + * n1 -> n2, n1 -> n2, n1 -> n4 * n2 -> n1, n2 -> n4 * n3 -> n4 * n4 -> n1, n4 -> n3 * - * multi-edges are stored in edges std::set */ class AdjacencyMatrixDirectedGraph : public IDirectedGraph @@ -51,7 +50,7 @@ public: private: std::set<DirectedEdge> edges; - std::unordered_map<Node, std::unordered_map<Node, bool>> adj; + std::unordered_map<Node, std::unordered_map<Node, int>> adj; }; } // namespace graph diff --git a/alib2data/src/graph/undirected/AdjacencyMatrixUndirectedGraph.cpp b/alib2data/src/graph/undirected/AdjacencyMatrixUndirectedGraph.cpp index bba341d080b283557a0412f332d2a5e2cccb89ee..49c50ba2e3977dd1e32d10721d728264685d4801 100644 --- a/alib2data/src/graph/undirected/AdjacencyMatrixUndirectedGraph.cpp +++ b/alib2data/src/graph/undirected/AdjacencyMatrixUndirectedGraph.cpp @@ -52,7 +52,7 @@ std::set<Node> AdjacencyMatrixUndirectedGraph::neighbors(const Node &node) const } for (auto i : search->second) { - if (i.second) { + if (i.second > 0) { out.insert(i.first); } } @@ -117,8 +117,8 @@ bool AdjacencyMatrixUndirectedGraph::addEdge(const UndirectedEdge &edge) edges.insert(edge); - adj[edge.getFirstNode()].insert({edge.getSecondNode(), true}); - adj[edge.getSecondNode()].insert({edge.getFirstNode(), true}); + adj[edge.getFirstNode()][edge.getSecondNode()]++; + adj[edge.getSecondNode()][edge.getFirstNode()]++; return true; } @@ -132,15 +132,18 @@ bool AdjacencyMatrixUndirectedGraph::removeEdge(const UndirectedEdge &edge) edges.erase(search); - // Don't touch adj if there still is an edge, in case of multigraph - if (findEdges(edge.getFirstNode(), edge.getSecondNode()).empty()) { - auto &map1 = adj[edge.getFirstNode()]; + auto &map1 = adj[edge.getFirstNode()]; + int &val1 = map1[edge.getSecondNode()]; + if (--val1 <= 0) { map1.erase(edge.getSecondNode()); if (map1.empty()) { adj.erase(edge.getFirstNode()); } + } - auto &map2 = adj[edge.getSecondNode()]; + auto &map2 = adj[edge.getSecondNode()]; + int &val2 = map2[edge.getFirstNode()]; + if (--val2 <= 0) { map2.erase(edge.getFirstNode()); if (map2.empty()) { adj.erase(edge.getSecondNode()); diff --git a/alib2data/src/graph/undirected/AdjacencyMatrixUndirectedGraph.h b/alib2data/src/graph/undirected/AdjacencyMatrixUndirectedGraph.h index 337d875d8b798550795de3231616b5b75df975c1..a877b030ab61ed92dbd946618f3ffb77a9989017 100644 --- a/alib2data/src/graph/undirected/AdjacencyMatrixUndirectedGraph.h +++ b/alib2data/src/graph/undirected/AdjacencyMatrixUndirectedGraph.h @@ -14,20 +14,19 @@ namespace graph { * * unordered_map: * [ -- ][ n1 ][ n2 ][ n3 ][ n4 ] - * [ n1 ] - x x x - * [ n2 ] x - - x - * [ n3 ] x - - x - * [ n4 ] x x x - + * [ n1 ] 0 2 1 1 + * [ n2 ] 2 0 0 1 + * [ n3 ] 1 0 0 1 + * [ n4 ] 1 1 1 0 * * edges: - * n1 <-> n2, n1 <-> n3, n1 <-> n4 + * n1 <-> n2, n1 <-> n2, n1 <-> n3, n1 <-> n4 * n2 <-> n4 * n3 <-> n4 * * undirected edge n1 <-> n2 is represented as * directed edge n1 -> n2 and directed edge n2 -> n1 * - * multi-edges are stored in edges std::set */ class AdjacencyMatrixUndirectedGraph : public IUndirectedGraph @@ -53,7 +52,7 @@ public: private: std::set<UndirectedEdge> edges; - std::unordered_map<Node, std::unordered_map<Node, bool>> adj; + std::unordered_map<Node, std::unordered_map<Node, int>> adj; }; } // namespace graph diff --git a/alib2data/test-src/graph/GraphTest.cpp b/alib2data/test-src/graph/GraphTest.cpp index f9f33a3e10d51072ef837931b33639543d203caa..9ae3f19f625d60e9e4721bffa6cb244de8304e91 100644 --- a/alib2data/test-src/graph/GraphTest.cpp +++ b/alib2data/test-src/graph/GraphTest.cpp @@ -329,22 +329,23 @@ void GraphTest::testRemoveEdge_impl(graph::REPRESENTATION representation) graph::DirectedGraph dg(representation); dg.addEdge(graph::DirectedEdge(n1, n2)); dg.addEdge(graph::DirectedEdge(n1, n2, "multi-edge")); + dg.addEdge(graph::DirectedEdge(n1, n3)); dg.addEdge(graph::DirectedEdge(n2, n3)); dg.addEdge(graph::DirectedEdge(n3, n4)); dg.addEdge(graph::DirectedEdge(n4, n1)); CPPUNIT_ASSERT_EQUAL_INT(4, dg.getNodes().size()); - CPPUNIT_ASSERT_EQUAL_INT(5, dg.getEdges().size()); + CPPUNIT_ASSERT_EQUAL_INT(6, dg.getEdges().size()); - CPPUNIT_ASSERT_EQUAL_INT(1, dg.neighbors(n1).size()); + CPPUNIT_ASSERT_EQUAL_INT(2, dg.neighbors(n1).size()); dg.removeEdge(graph::DirectedEdge(n1, n2)); CPPUNIT_ASSERT_EQUAL_INT(1, dg.findEdges(n1, n2).size()); - CPPUNIT_ASSERT_EQUAL_INT(1, dg.neighbors(n1).size()); + CPPUNIT_ASSERT_EQUAL_INT(2, dg.neighbors(n1).size()); - CPPUNIT_ASSERT_EQUAL_INT(1, dg.neighbors(n1).size()); + CPPUNIT_ASSERT_EQUAL_INT(2, dg.neighbors(n1).size()); dg.removeEdge(graph::DirectedEdge(n1, n2, "multi-edge")); CPPUNIT_ASSERT_EQUAL_INT(0, dg.findEdges(n1, n2).size()); - CPPUNIT_ASSERT_EQUAL(true, dg.neighbors(n1).empty()); + CPPUNIT_ASSERT_EQUAL_INT(1, dg.neighbors(n1).size()); CPPUNIT_ASSERT_EQUAL_INT(1, dg.neighbors(n2).size()); dg.removeEdge(graph::DirectedEdge(n2, n3)); @@ -361,6 +362,11 @@ void GraphTest::testRemoveEdge_impl(graph::REPRESENTATION representation) CPPUNIT_ASSERT_EQUAL_INT(0, dg.findEdges(n4, n1).size()); CPPUNIT_ASSERT_EQUAL(true, dg.neighbors(n4).empty()); + CPPUNIT_ASSERT_EQUAL_INT(1, dg.neighbors(n1).size()); + dg.removeEdge(graph::DirectedEdge(n1, n3)); + CPPUNIT_ASSERT_EQUAL_INT(0, dg.findEdges(n1, n3).size()); + CPPUNIT_ASSERT_EQUAL(true, dg.neighbors(n1).empty()); + CPPUNIT_ASSERT_EQUAL(true, dg.getEdges().empty()); CPPUNIT_ASSERT_EQUAL(true, dg.getNodes().empty());