From c89e0bfc3a86eab3d6385c00bd7b259c2f3fad1f Mon Sep 17 00:00:00 2001 From: dmatetelki Date: Wed, 30 Jul 2014 14:09:13 +0200 Subject: [PATCH] Graph stands for not weighed, not directed graph. --- .gitignore | 2 +- CMakeLists.txt | 3 - lib/graph/graph.hpp | 256 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 257 insertions(+), 4 deletions(-) create mode 100644 lib/graph/graph.hpp diff --git a/.gitignore b/.gitignore index 5124bd9..e5ad2c3 100644 --- a/.gitignore +++ b/.gitignore @@ -5,6 +5,6 @@ CMakeFiles/* Makefile build/* cmake_install.cmake -graph +# graph graph.kdev4 libstdcxx-profile.* diff --git a/CMakeLists.txt b/CMakeLists.txt index 8903062..28ae19c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,7 +1,4 @@ cmake_minimum_required (VERSION 2.6) project (PROJECT_GRAPH) -set(CMAKE_CXX_FLAGS " -Wall -Wextra -pedantic -Weffc++ -Wshadow --std=c++0x -ggdb") -set(CMAKE_CXX_COMPILER "/usr/lib/colorgcc/bin/g++") - add_subdirectory (test) diff --git a/lib/graph/graph.hpp b/lib/graph/graph.hpp new file mode 100644 index 0000000..803f2a3 --- /dev/null +++ b/lib/graph/graph.hpp @@ -0,0 +1,256 @@ +#ifndef GRAPHWD_HPP +#define GRAPHWD_HPP + +#include +#include + +#include +#include + +// not weighed, not directed +// multiedges, self edges are not checked +// V expected to be cheap to store aggregate + +template +class Graph { + +public: + + typedef size_t size_type; + typedef V value_type; + typedef V* pointer; + typedef const V* const_pointer; + typedef V& reference; + typedef const V& const_reference; + typedef std::ptrdiff_t difference_type; + +private: + + typedef std::unordered_map > v_container; + typedef typename v_container::iterator v_iterator; + typedef typename v_container::const_iterator v_const_iterator; + +public: + + struct Edge { + Edge() : source(), destination() {} + Edge(const_reference s, const_reference d) : source(s), destination(d) {} + Edge(const Edge& o) : source(o.source), destination(o.destination) {} + Edge& operator=(Edge o) { swap(o); return *this; } + void swap(Edge& o) { std::swap(source, o.source); std::swap(destination, o.destination); } + bool operator==(const Edge& o) const { return source == o.source && destination == o.destination; } + + value_type source; + value_type destination; + }; + + Graph() : m_vertices() {} + Graph(const Graph& o) : m_vertices(o.m_vertices) {} + Graph(std::initializer_list vertex_list); + Graph(std::initializer_list edge_list); + + Graph& operator=(Graph o) { swap(o); return *this; } + void swap(Graph& o) { std::swap(m_vertices, o.m_vertices); } + + // Capacity + bool empty() const { return m_vertices.empty(); } + size_type numberOfVertices() const { return m_vertices.size(); } + size_type numberOfEdges() const; + + // Modifiers + void clear() { m_vertices.clear(); } + + void addVertex(const_reference data); + void removeVertex(const_reference data); + void addEdge(const_reference source, const_reference destination); + void setEdges(const_reference source, const std::vector& destinations); + void removeEdge(const_reference source, const_reference destination); + + // Lookup + bool contains(const_reference data) const { return m_vertices.find(data) != m_vertices.end(); } + std::vector vertices() const; + std::vector neighboursOf(const_reference data) const; + std::vector edges() const; + + // iterator + class vertex_iterator : public std::iterator + { + friend class Graph; + + public: + typedef vertex_iterator self_type; + typedef vertex_iterator& reference_self_type; + typedef const vertex_iterator& const_reference_self_type; + + vertex_iterator() : m_it() {} + ~vertex_iterator() {} + vertex_iterator(const_reference_self_type o) : m_it(o.m_it) {} + reference_self_type operator=(self_type o) { swap(o); return *this; } + void swap(reference_self_type o) { std::swap(m_it, o.m_it); } + + const_reference operator*() { return m_it->first; } + const_pointer operator->() { return &m_it->first; } + self_type &operator++() { ++m_it; return *this; } + self_type operator++(int) { self_type tmp(*this); ++(*this); return tmp; } + self_type operator+(difference_type n) { self_type tmp(*this); tmp.pos_ += n; return tmp; } + self_type &operator+=(difference_type n) { m_it += n; return *this; } + bool operator==(const_reference_self_type o) const { return m_it == o.m_it; } + bool operator!=(const_reference_self_type o) const { return !(*this == o); } + + private: + vertex_iterator(v_iterator it) : m_it(it) {} + vertex_iterator(v_const_iterator it) : m_it(it) {} + + v_const_iterator m_it; + }; + + typedef vertex_iterator iterator; + typedef const vertex_iterator const_iterator; + + iterator begin() { return iterator(m_vertices.begin()); } + iterator begin() const { return iterator(m_vertices.begin()); } + const_iterator cbegin() const { return const_iterator(m_vertices.begin()); } + iterator end() { return iterator(m_vertices.end()); } + iterator end() const { return iterator(m_vertices.end()); } + const_iterator cend() const { return const_iterator(m_vertices.end()); } + +private: + + static void eraseEdge(typename std::vector& v, const_reference data); + + v_container m_vertices; +}; + + +// Graph + +template +inline Graph::Graph(std::initializer_list vertex_list) + : Graph() +{ + for(const V& v : vertex_list) + addVertex(v); +} + +template +inline Graph::Graph(std::initializer_list edge_list) + : Graph() +{ + for (const Edge& e : edge_list ) + addEdge(e.source, e.destination, e.weight); +} + +template +inline typename Graph::size_type Graph::numberOfEdges() const +{ + int sum = 0; + for (const auto& v : m_vertices) + sum += v.second.size(); + + return sum; +} + +template +inline void Graph::addVertex(const_reference data) +{ + if (m_vertices.find(data) != m_vertices.end()) + return; + + std::pair > p(data, std::vector()); + m_vertices.insert(p); +} + +template +inline void Graph::removeVertex(const_reference data) +{ + v_iterator it = m_vertices.find(data); + if (it == m_vertices.end()) + return; + + for (auto &v : m_vertices) + eraseEdge(v.second, data); + + m_vertices.erase(it); +} + +template +inline void Graph::addEdge(const_reference source, const_reference destination) +{ + addVertex(source); + addVertex(destination); + + v_iterator source_it = m_vertices.find(source); + v_iterator destination_it = m_vertices.find(destination); + + source_it->second.push_back(destination); + destination_it->second.push_back(source); +} + +template +inline void Graph::setEdges(const_reference source, const std::vector& destinations) +{ + addVertex(source); + v_iterator source_it = m_vertices.find(source); + + source_it->second.clear(); + source_it->second.reserve(destinations.size()); // it is needed? + source_it->second = destinations; +} + +template +inline void Graph::removeEdge(const_reference source, const_reference destination) +{ + v_iterator source_it = m_vertices.find(source); + if (source_it == m_vertices.end()) + return; + + v_iterator destination_it = m_vertices.find(destination); + if (destination_it == m_vertices.end()) + return; + + eraseEdge(source_it->second, destination); + eraseEdge(destination_it->second, source); +} + +template +inline std::vector::value_type> Graph::vertices() const +{ + std::vector retval; + for (const auto& v : m_vertices) + retval.push_back(v.first); + + return retval; +} + +template +inline std::vector Graph::neighboursOf(const_reference data) const +{ + v_const_iterator vertex_it = m_vertices.find(data); + if (vertex_it == m_vertices.end()) + return std::vector(); + else + return vertex_it->second; +} + +template +inline std::vector::Edge> Graph::edges() const +{ + std::vector::Edge> retval; + for (const auto& v : m_vertices) + for (const auto& e : v.second) + retval.push_back(Graph::Edge(v.first, e)); + + return retval; +} + +template +inline void Graph::eraseEdge(typename std::vector& v, const_reference data) { + v.erase(std::remove(v.begin(), v.end()), v.end()); +} + + +#endif // GRAPHWD_HPP