From 4b5d8c4f5e708a806151ebc6d9c824206aabbb5e Mon Sep 17 00:00:00 2001 From: David Rosca <roscadav@fit.cvut.cz> Date: Thu, 5 Mar 2015 15:33:24 +0100 Subject: [PATCH] AdjacencyMatrix representation: Use int as a value of map It now stores number of edges, instead of just bool indicating that there is an edge --- .../directed/AdjacencyMatrixDirectedGraph.cpp | 10 +++++----- .../directed/AdjacencyMatrixDirectedGraph.h | 13 ++++++------- .../AdjacencyMatrixUndirectedGraph.cpp | 17 ++++++++++------- .../undirected/AdjacencyMatrixUndirectedGraph.h | 13 ++++++------- alib2data/test-src/graph/GraphTest.cpp | 16 +++++++++++----- 5 files changed, 38 insertions(+), 31 deletions(-) diff --git a/alib2data/src/graph/directed/AdjacencyMatrixDirectedGraph.cpp b/alib2data/src/graph/directed/AdjacencyMatrixDirectedGraph.cpp index e27b234367..6bcdb3dc42 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 a3f9915d0c..5dc9aa4adc 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 bba341d080..49c50ba2e3 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 337d875d8b..a877b030ab 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 f9f33a3e10..9ae3f19f62 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()); -- GitLab