#ifndef GRAPH_H #define GRAPH_H #include #include #include #include // directed, weighted /// @todo weight type as param too? template class Graph { public: typedef size_t size_type; typedef T value_type; typedef T* pointer; typedef const T* const_pointer; typedef T& reference; typedef const T& const_reference; typedef std::ptrdiff_t difference_type; private: struct EdgeTo { EdgeTo(const_reference destination, float weight = 0); EdgeTo(const EdgeTo& other); EdgeTo& operator=(const EdgeTo& other); pointer m_destination; float m_weight; }; struct Vertex { Vertex(const_reference data); Vertex(const Vertex& other); Vertex& operator=(const Vertex& other); void addEdge(const_reference destination, float weight = 0); void removeEdge(const_reference destination, float weight = 0); void removeAllEdgesTo(const_reference destination); pointer m_data; std::list m_edges; }; public: Graph(); // Capacity bool empty() const; size_type numberOfVertices() const; size_type numberOfEdges() const; // Modifiers bool addVertex(const_reference data); bool removeVertex(const_reference data); bool addEdge(const_reference source, const_reference destination, float weight = 0); bool removeEdge(const_reference source, const_reference destination, float weight = 0); bool removeAllEdges(const_reference source, const_reference destination); // Lookup bool contains(const_reference data) const; std::vector vertices() const; std::vector neighboursOf(const_reference data) const; std::vector edgesBetween(const_reference source, const_reference destination) const; private: Graph(const Graph& o) { /** @todo impelemnt me */ } Graph& operator=(const Graph& o) { /** @todo impelemnt me */ } typename std::vector::const_iterator find(const_reference data) const; typename std::vector::iterator find(const_reference data); std::vector m_vertices; public: class iterator : public std::iterator { public: typedef iterator self_type; typedef iterator& reference_self_type; typedef const iterator& const_reference_self_type; iterator() : m_it() {} iterator(typename std::vector::iterator it) : m_it(it) {} ~iterator() {} iterator(const_reference_self_type o) : m_it(o.m_it) {} reference_self_type operator=(const_reference_self_type o) { if (this != &o) { m_it = o.m_it; } return *this; } reference operator*() { return *((*m_it).m_data); } pointer operator->() { return (*m_it).m_data; } 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) { return m_it == o.m_it; } bool operator!=(const_reference_self_type o) { return !(*this == o); } private: typename std::vector::iterator m_it; }; iterator begin() { return iterator(m_vertices.begin()); } iterator end() { return iterator(m_vertices.begin()); } /// @todo const iterator and cbegin and cend }; // Edge template Graph::EdgeTo::EdgeTo(const_reference destination, float weight) : m_destination(const_cast(&destination)) , m_weight(weight) { } template Graph::EdgeTo::EdgeTo(const EdgeTo& other) : m_destination(other.m_destination) , m_weight(other.m_weight) { } template typename Graph::EdgeTo& Graph::EdgeTo::operator=(const EdgeTo& other) { if (this != &other) { m_destination = other.m_destination; m_weight = other.m_weight; } return *this; } // Vertex template Graph::Vertex::Vertex(const_reference data) : m_data(const_cast(&data)) , m_edges() { } template Graph::Vertex::Vertex(const Vertex& other) : m_data(other.m_data) , m_edges(other.m_edges) { } template typename Graph::Vertex& Graph::Vertex::operator=(const Vertex& other) { if (this != &other) { m_data = other.m_data; m_edges.clear(); m_edges = other.m_edges; } return *this; } template void Graph::Vertex::addEdge(const_reference destination, float weight) { EdgeTo e(destination, weight); m_edges.push_back(e); } template void Graph::Vertex::removeEdge(const_reference destination, float weight) { m_edges.erase(std::find_if(m_edges.begin(), m_edges.end(), [&destination, &weight](const EdgeTo& e) { return e.m_destination == destination && e.m_weight == weight;})); } template void Graph::Vertex::removeAllEdgesTo(const_reference destination) { std::remove_if(m_edges.begin(), m_edges.end(), [&destination](const EdgeTo& e) { return e.m_destination == destination; }); } // Graph template Graph::Graph() : m_vertices() { } template bool Graph::empty() const { return m_vertices.empty(); } template typename Graph::size_type Graph::numberOfVertices() const { return m_vertices.size(); } template typename Graph::size_type Graph::numberOfEdges() const { return std::accumulate(m_vertices.begin(), m_vertices.end(), 0, [](int sum, const Vertex& v) { return sum + v.m_edges.size(); }); } template bool Graph::addVertex(const_reference data) { if (find(data) != m_vertices.end()) return false; Vertex v(data); m_vertices.push_back(v); return true; } template bool Graph::removeVertex(const_reference data) { typename std::vector::iterator it = find(data); if (it == m_vertices.end()) return false; m_vertices.erase(it); return true; } template bool Graph::addEdge(const_reference source, const_reference destination, float weight) { typename std::vector::iterator source_it = find(source); if (source_it == m_vertices.end()) return false; typename std::vector::iterator destination_it = find(destination); if (destination_it == m_vertices.end()) return false; (*source_it).addEdge(destination, weight); return true; } template bool Graph::removeEdge(const_reference source, const_reference destination, float weight) { typename std::vector::iterator it = find(source); if (it == m_vertices.end()) return false; (*it).removeEdge(destination, weight); return true; } template bool Graph::removeAllEdges(const_reference source, const_reference destination) { typename std::vector::iterator it = find(source); if (it == m_vertices.end()) return false; (*it).removeAllEdgesEdge(destination); return true; } template bool Graph::contains(const_reference data) const { return find(data) != m_vertices.end(); } template std::vector::pointer> Graph::vertices() const { std::vector retval; std::for_each(m_vertices.begin(), m_vertices.end(), [&retval](const Vertex& v) { retval.push_back(v.m_data); }); return retval; } template std::vector::pointer> Graph::neighboursOf(const_reference data) const { typename std::vector retval; typename std::vector::const_iterator vertex_it = find(data); if (vertex_it == m_vertices.end()) return retval; std::for_each((*vertex_it).m_edges.begin(), (*vertex_it).m_edges.end(), [&retval](const EdgeTo& e) { retval.push_back(e.m_destination); }); return retval; } template std::vector Graph::edgesBetween(const_reference source, const_reference destination) const { std::vector retval; typename std::vector::const_iterator vertex_it = find(source); if (vertex_it == m_vertices.end()) return retval; std::for_each((*vertex_it).m_edges.begin(), (*vertex_it).m_edges.end(), [&retval, &destination](const EdgeTo& e) { if (*(e.m_destination) == destination) retval.push_back(e.m_weight); }); return retval; } template typename std::vector::Vertex >::const_iterator Graph::find(const_reference data) const { return std::find_if(m_vertices.begin(), m_vertices.end(), [&data](const Vertex& v) { return *(v.m_data) == data; }); } template typename std::vector::Vertex >::iterator Graph::find(const_reference data) { return std::find_if(m_vertices.begin(), m_vertices.end(), [&data](const Vertex& v) { return *(v.m_data) == data; }); } #endif // GRAPH_H