diff --git a/alib2data/src/graph/directed/AdjacencyListDirectedGraph.cpp b/alib2data/src/graph/directed/AdjacencyListDirectedGraph.cpp index 1e308ded42627bbe97c2a8abddd0e6308b0c8a81..378b3ade51699a395454352bbae4c14f19e4478b 100644 --- a/alib2data/src/graph/directed/AdjacencyListDirectedGraph.cpp +++ b/alib2data/src/graph/directed/AdjacencyListDirectedGraph.cpp @@ -5,6 +5,11 @@ namespace graph { +inline void listRemoveOne(std::list<Node> &lst, const Node &node) +{ + lst.erase(std::find(lst.begin(), lst.end(), node)); +} + std::set<Node> AdjacencyListDirectedGraph::allNodes() const { std::set<Node> out; @@ -82,7 +87,10 @@ bool AdjacencyListDirectedGraph::removeNode(const Node &node) auto i = edges.begin(); while (i != edges.end()) { - if (i->getFromNode() == node || i->getToNode() == node) { + if (i->getFromNode() == node) { + edges.erase(i++); + } else if (i->getToNode() == node) { + listRemoveOne(adj[i->getFromNode()], node); edges.erase(i++); } else { i++; @@ -115,7 +123,7 @@ bool AdjacencyListDirectedGraph::removeEdge(const DirectedEdge &edge) edges.erase(search); auto &lst = adj[edge.getFromNode()]; - lst.erase(std::find(lst.begin(), lst.end(), edge.getToNode())); + listRemoveOne(lst, edge.getToNode()); if (lst.empty()) { adj.erase(edge.getFromNode()); } diff --git a/alib2data/src/graph/undirected/AdjacencyListUndirectedGraph.cpp b/alib2data/src/graph/undirected/AdjacencyListUndirectedGraph.cpp index 6420331045059190c6f5198621da1889874c8e38..dd97ccbf5019b3c049f4534679ce6846554bfa74 100644 --- a/alib2data/src/graph/undirected/AdjacencyListUndirectedGraph.cpp +++ b/alib2data/src/graph/undirected/AdjacencyListUndirectedGraph.cpp @@ -27,6 +27,11 @@ static bool edgeMatch(const UndirectedEdge &edge, const Node &node, const std::s return false; } +inline void listRemoveOne(std::list<Node> &lst, const Node &node) +{ + lst.erase(std::find(lst.begin(), lst.end(), node)); +} + std::set<Node> AdjacencyListUndirectedGraph::allNodes() const { std::set<Node> out; @@ -104,7 +109,11 @@ bool AdjacencyListUndirectedGraph::removeNode(const Node &node) auto i = edges.begin(); while (i != edges.end()) { - if (i->getFirstNode() == node || i->getSecondNode() == node) { + if (i->getFirstNode() == node) { + listRemoveOne(adj[i->getSecondNode()], node); + edges.erase(i++); + } else if (i->getSecondNode() == node) { + listRemoveOne(adj[i->getFirstNode()], node); edges.erase(i++); } else { i++; @@ -138,13 +147,13 @@ bool AdjacencyListUndirectedGraph::removeEdge(const UndirectedEdge &edge) edges.erase(search); auto &lst1 = adj[edge.getFirstNode()]; - lst1.erase(std::find(lst1.begin(), lst1.end(), edge.getSecondNode())); + listRemoveOne(lst1, edge.getSecondNode()); if (lst1.empty()) { adj.erase(edge.getFirstNode()); } auto &lst2 = adj[edge.getSecondNode()]; - lst2.erase(std::find(lst2.begin(), lst2.end(), edge.getFirstNode())); + listRemoveOne(lst2, edge.getFirstNode()); if (lst2.empty()) { adj.erase(edge.getSecondNode()); } diff --git a/alib2data/test-src/graph/GraphTest.cpp b/alib2data/test-src/graph/GraphTest.cpp index 36a3359947f2a4908d07701b98468522996bc50d..c22bf267698a2333cd0287c847dddb2242a5a540 100644 --- a/alib2data/test-src/graph/GraphTest.cpp +++ b/alib2data/test-src/graph/GraphTest.cpp @@ -353,3 +353,110 @@ void GraphTest::testRemoveEdge() CPPUNIT_ASSERT(ug.getNodes().empty()); } +void GraphTest::testAddNode() +{ + // Directed + graph::DirectedGraph dg(graph::REPRESENTATION::ADJACENCY_LIST); + + CPPUNIT_ASSERT(dg.getNodes().size() == 0); + dg.addNode(graph::Node("n1")); + CPPUNIT_ASSERT(dg.getNodes().size() == 1); + dg.addNode(graph::Node("n2")); + CPPUNIT_ASSERT(dg.getNodes().size() == 2); + + CPPUNIT_ASSERT(dg.addNode(graph::Node("n2")) == false); + CPPUNIT_ASSERT(dg.getNodes().size() == 2); + + dg.addNode(graph::Node("n3")); + CPPUNIT_ASSERT(dg.getNodes().size() == 3); + dg.addNode(graph::Node("n4")); + CPPUNIT_ASSERT(dg.getNodes().size() == 4); + dg.addNode(graph::Node("n5")); + CPPUNIT_ASSERT(dg.getNodes().size() == 5); + + // Undirected + graph::UndirectedGraph ug(graph::REPRESENTATION::ADJACENCY_LIST); + + CPPUNIT_ASSERT(ug.getNodes().size() == 0); + ug.addNode(graph::Node("n1")); + CPPUNIT_ASSERT(ug.getNodes().size() == 1); + ug.addNode(graph::Node("n2")); + CPPUNIT_ASSERT(ug.getNodes().size() == 2); + + CPPUNIT_ASSERT(ug.addNode(graph::Node("n2")) == false); + CPPUNIT_ASSERT(ug.getNodes().size() == 2); + + ug.addNode(graph::Node("n3")); + CPPUNIT_ASSERT(ug.getNodes().size() == 3); + ug.addNode(graph::Node("n4")); + CPPUNIT_ASSERT(ug.getNodes().size() == 4); + ug.addNode(graph::Node("n5")); + CPPUNIT_ASSERT(ug.getNodes().size() == 5); +} + +void GraphTest::testRemoveNode() +{ + // Common + graph::Node n1("n1"); + graph::Node n2("n2"); + graph::Node n3("n3"); + graph::Node n4("n4"); + + // Directed + graph::DirectedGraph dg(graph::REPRESENTATION::ADJACENCY_LIST); + dg.addEdge(graph::DirectedEdge(n1, n2)); + dg.addEdge(graph::DirectedEdge(n1, n2, "multi-edge")); + dg.addEdge(graph::DirectedEdge(n2, n3)); + dg.addEdge(graph::DirectedEdge(n3, n4)); + dg.addEdge(graph::DirectedEdge(n4, n1)); + + CPPUNIT_ASSERT(dg.getNodes().size() == 4); + CPPUNIT_ASSERT(dg.getEdges().size() == 5); + + dg.removeNode(n1); + CPPUNIT_ASSERT(dg.neighbors(n4).empty()); + CPPUNIT_ASSERT(dg.findEdges(n1, n2).empty()); + CPPUNIT_ASSERT(dg.findEdges(n4, n1).empty()); + + dg.removeNode(n2); + CPPUNIT_ASSERT(dg.findEdges(n2, n3).empty()); + + dg.removeNode(n3); + CPPUNIT_ASSERT(dg.findEdges(n3, n4).empty()); + + dg.removeNode(n4); + CPPUNIT_ASSERT(dg.findEdges(n4, n1).empty()); + + CPPUNIT_ASSERT(dg.getEdges().empty()); + CPPUNIT_ASSERT(dg.getNodes().empty()); + + // Undirected + graph::UndirectedGraph ug(graph::REPRESENTATION::ADJACENCY_LIST); + ug.addEdge(graph::UndirectedEdge(n1, n2)); + ug.addEdge(graph::UndirectedEdge(n1, n2, "multi-edge")); + ug.addEdge(graph::UndirectedEdge(n2, n3)); + ug.addEdge(graph::UndirectedEdge(n3, n4)); + ug.addEdge(graph::UndirectedEdge(n4, n1)); + + CPPUNIT_ASSERT(ug.getNodes().size() == 4); + CPPUNIT_ASSERT(ug.getEdges().size() == 5); + + ug.removeNode(n1); + CPPUNIT_ASSERT(ug.neighbors(n4).size() == 1); + CPPUNIT_ASSERT(ug.findEdges(n1, n2).empty()); + CPPUNIT_ASSERT(ug.findEdges(n4, n1).empty()); + + ug.removeNode(n2); + CPPUNIT_ASSERT(ug.findEdges(n2, n3).empty()); + + ug.removeNode(n3); + CPPUNIT_ASSERT(ug.neighbors(n4).empty()); + CPPUNIT_ASSERT(ug.findEdges(n3, n4).empty()); + + ug.removeNode(n4); + CPPUNIT_ASSERT(ug.findEdges(n4, n1).empty()); + + CPPUNIT_ASSERT(ug.getEdges().empty()); + CPPUNIT_ASSERT(ug.getNodes().empty()); +} + diff --git a/alib2data/test-src/graph/GraphTest.h b/alib2data/test-src/graph/GraphTest.h index c2f4147fc58eac3a71abfd5831a4601e4ec9057e..0e980da0f4db532c733673b2e19326ff31f6072a 100644 --- a/alib2data/test-src/graph/GraphTest.h +++ b/alib2data/test-src/graph/GraphTest.h @@ -12,6 +12,8 @@ class GraphTest : public CppUnit::TestFixture CPPUNIT_TEST(testStringParser); CPPUNIT_TEST(testAddEdge); CPPUNIT_TEST(testRemoveEdge); + CPPUNIT_TEST(testAddNode); + CPPUNIT_TEST(testRemoveNode); CPPUNIT_TEST_SUITE_END(); public: @@ -25,6 +27,8 @@ public: void testAddEdge(); void testRemoveEdge(); + void testAddNode(); + void testRemoveNode(); }; #endif // GRAPH_TEST_H_