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