From 623dc45a59b4365dd1784fcf31c45e9146b81053 Mon Sep 17 00:00:00 2001 From: David Rosca <roscadav@fit.cvut.cz> Date: Sun, 1 Mar 2015 17:22:34 +0100 Subject: [PATCH] Add AdjacencyListUndirectedGraph --- alib2data/src/graph/GraphFromXMLParser.cpp | 2 + .../AdjacencyListUndirectedGraph.cpp | 147 ++++++++++++++++++ .../undirected/AdjacencyListUndirectedGraph.h | 37 +++++ .../src/graph/undirected/UndirectedGraph.cpp | 4 + 4 files changed, 190 insertions(+) create mode 100644 alib2data/src/graph/undirected/AdjacencyListUndirectedGraph.cpp create mode 100644 alib2data/src/graph/undirected/AdjacencyListUndirectedGraph.h diff --git a/alib2data/src/graph/GraphFromXMLParser.cpp b/alib2data/src/graph/GraphFromXMLParser.cpp index d44bc3c173..c3bc16786b 100644 --- a/alib2data/src/graph/GraphFromXMLParser.cpp +++ b/alib2data/src/graph/GraphFromXMLParser.cpp @@ -18,6 +18,8 @@ Graph GraphFromXMLParser::parseGraph(std::list<sax::Token> &input) const { if (alib::xmlApi<DirectedGraph>::first(input)) { return Graph(parseDirectedGraph(input)); + } else if (alib::xmlApi<UndirectedGraph>::first(input)) { + return Graph(parseUndirectedGraph(input)); } throw exception::AlibException(); diff --git a/alib2data/src/graph/undirected/AdjacencyListUndirectedGraph.cpp b/alib2data/src/graph/undirected/AdjacencyListUndirectedGraph.cpp new file mode 100644 index 0000000000..91f589a069 --- /dev/null +++ b/alib2data/src/graph/undirected/AdjacencyListUndirectedGraph.cpp @@ -0,0 +1,147 @@ +#include "AdjacencyListUndirectedGraph.h" +#include "../../std/compare.hpp" + +namespace graph { + +static bool edgeMatch(const UndirectedEdge &edge, const Node &first, const Node &second) +{ + if (edge.getFirstNode() == first && edge.getSecondNode() == second) { + return true; + } + if (edge.getFirstNode() == second && edge.getSecondNode() == first) { + return true; + } + return false; +} + +static bool edgeMatch(const UndirectedEdge &edge, const Node &node, const std::set<Node> &neighbors) +{ + if (edge.getFirstNode() == node && neighbors.find(edge.getSecondNode()) != neighbors.end()) { + return true; + } + if (edge.getSecondNode() == node && neighbors.find(edge.getFirstNode()) != neighbors.end()) { + return true; + } + return false; +} + +std::set<Node> AdjacencyListUndirectedGraph::allNodes() const +{ + std::set<Node> out; + + for (auto i : adj) { + out.insert(i.first); + } + + return out; +} + +std::set<UndirectedEdge> AdjacencyListUndirectedGraph::allEdges() const +{ + return edges; +} + +std::set<UndirectedEdge> AdjacencyListUndirectedGraph::findEdges(const Node &first, const Node &second) const +{ + std::set<UndirectedEdge> out; + + for (const UndirectedEdge &e : edges) { + if (edgeMatch(e, first, second)) { + out.insert(e); + } + } + + return out; +} + +std::set<Node> AdjacencyListUndirectedGraph::neighbors(const Node &node) const +{ + auto search = adj.find(node); + if (search == adj.end()) { + return std::set<Node>(); + } + return search->second; +} + +std::set<UndirectedEdge> AdjacencyListUndirectedGraph::neighborEdges(const Node &node) const +{ + std::set<UndirectedEdge> out; + const std::set<Node> &nghbrs = neighbors(node); + + for (const UndirectedEdge &e : edges) { + if (edgeMatch(e, node, nghbrs)) { + out.insert(e); + } + } + + return out; +} + +void AdjacencyListUndirectedGraph::addNode(const Node &node) +{ + if (adj.find(node) != adj.end()) { + return; + } + + adj[node]; // insert key +} + +void AdjacencyListUndirectedGraph::removeNode(const Node &node) +{ + auto search = adj.find(node); + if (search == adj.end()) { + return; + } + + adj.erase(search); + + auto i = edges.begin(); + while (i != edges.end()) { + if (i->getFirstNode() == node || i->getSecondNode() == node) { + edges.erase(i++); + } else { + i++; + } + } +} + +void AdjacencyListUndirectedGraph::addEdge(const UndirectedEdge &edge) +{ + if (edges.find(edge) != edges.end()) { + return; + } + + edges.insert(edge); + + adj[edge.getFirstNode()].insert(edge.getSecondNode()); + adj[edge.getSecondNode()].insert(edge.getFirstNode()); +} + +void AdjacencyListUndirectedGraph::removeEdge(const UndirectedEdge &edge) +{ + auto search = edges.find(edge); + if (search == edges.end()) { + return; + } + + edges.erase(search); + + // Don't touch adj if there still is an edge, in case of multigraph + if (!findEdges(edge.getFirstNode(), edge.getSecondNode()).empty()) { + adj[edge.getFirstNode()].erase(edge.getSecondNode()); + adj[edge.getSecondNode()].erase(edge.getFirstNode()); + } +} + +int AdjacencyListUndirectedGraph::compare(IUndirectedGraph *other) const +{ + AdjacencyListUndirectedGraph *o = static_cast<AdjacencyListUndirectedGraph*>(other); + + auto first = std::tie(edges, adj); + auto second = std::tie(o->edges, o->adj); + + std::compare<decltype(first)> comp; + return comp(first, second); +} + +} // namespace graph diff --git a/alib2data/src/graph/undirected/AdjacencyListUndirectedGraph.h b/alib2data/src/graph/undirected/AdjacencyListUndirectedGraph.h new file mode 100644 index 0000000000..3bd5de77a8 --- /dev/null +++ b/alib2data/src/graph/undirected/AdjacencyListUndirectedGraph.h @@ -0,0 +1,37 @@ +#ifndef ADJACENCY_LIST_UNDIRECTED_GRAPH_H_ +#define ADJACENCY_LIST_UNDIRECTED_GRAPH_H_ + +#include <set> +#include <unordered_map> + +#include "IUndirectedGraph.h" + +namespace graph { + +class AdjacencyListUndirectedGraph : public IUndirectedGraph +{ +public: + std::set<Node> allNodes() const override; + std::set<UndirectedEdge> allEdges() const override; + + std::set<UndirectedEdge> findEdges(const Node &first, const Node &second) const override; + + std::set<Node> neighbors(const Node &node) const override; + std::set<UndirectedEdge> neighborEdges(const Node &node) const override; + + void addNode(const Node &node) override; + void removeNode(const Node &node) override; + + void addEdge(const UndirectedEdge &edge) override; + void removeEdge(const UndirectedEdge &edge) override; + + int compare(IUndirectedGraph *other) const override; + +private: + std::set<UndirectedEdge> edges; + std::unordered_map<Node, std::set<Node>> adj; +}; + +} // namespace graph + +#endif // ADJACENCY_LIST_DIRECTED_GRAPH_H_ diff --git a/alib2data/src/graph/undirected/UndirectedGraph.cpp b/alib2data/src/graph/undirected/UndirectedGraph.cpp index cfd3ccbc53..2cbdd5fe8f 100644 --- a/alib2data/src/graph/undirected/UndirectedGraph.cpp +++ b/alib2data/src/graph/undirected/UndirectedGraph.cpp @@ -1,5 +1,6 @@ #include "UndirectedGraph.h" #include "IUndirectedGraph.h" +#include "AdjacencyListUndirectedGraph.h" #include "../../std/set.hpp" #include <iostream> @@ -139,6 +140,9 @@ void UndirectedGraph::init() { switch (representation) { case REPRESENTATION::ADJACENCY_LIST: + impl = new AdjacencyListUndirectedGraph(); + break; + case REPRESENTATION::ADJACENCY_MATRIX: case REPRESENTATION::INCIDENCE_MATRIX: -- GitLab