From a7fad9cfb0d4b2776335162833023346f806176c Mon Sep 17 00:00:00 2001 From: Denes Matetelki Date: Sat, 23 Feb 2013 23:35:46 +0100 Subject: [PATCH] first commit --- CMakeLists.txt | 15 ++ graph.h | 388 +++++++++++++++++++++++++++++++++++++++++++++++++ main.cpp | 41 ++++++ 3 files changed, 444 insertions(+) create mode 100644 CMakeLists.txt create mode 100644 graph.h create mode 100644 main.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..272bed7 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,15 @@ +cmake_minimum_required (VERSION 2.6) + +project(graph) + + +set(CMAKE_CXX_COMPILER "/usr/lib/colorgcc/bin/g++") +# set(CMAKE_CXX_COMPILER "/usr/bin/clang") + +set (CXX_FLAGS "-Wall -Wextra -pedantic -Weffc++ -Wshadow " + "-ggdb -std=c++0x -D_GLIBCXX_PROFILE ") +add_definitions( ${CXX_FLAGS} ) + +# include_directories(.) + +add_executable(graph main.cpp) diff --git a/graph.h b/graph.h new file mode 100644 index 0000000..dcb3937 --- /dev/null +++ b/graph.h @@ -0,0 +1,388 @@ +#ifndef GRAPH_H +#define GRAPH_H + +#include +#include + +// directed, weighted +template +class Graph { + +private: + + struct Edge { + + Edge(const T& destination, float weight = 0); + Edge(const Edge& other); + Edge& operator=(const Edge& other); + + const T* m_destination; + float m_weight; + }; + + struct Vertex { + + Vertex(const T& data); + Vertex(const Vertex& other); + Vertex& operator=(const Vertex& other); + void addEdge(const T& destination, float weight = 0); + void removeEdge(const T& destination, float weight = 0); + void removeAllEdgesTo(const T& destination); + + const T* m_data; + std::vector m_edges; + }; + + +public: + + Graph(); + + // Capacity + bool empty() const; + size_t numberOfVertices() const; + size_t numberOfEdges() const; + + // Modifiers + bool addVertex(const T& data); + bool removeVertex(const T& data); + bool addEdge(const T& source, const T& destination, float weight = 0); + bool removeEdge(const T& source, const T& destination, float weight = 0); + bool removeAllEdges(const T& source, const T& destination); + + // Lookup + bool contains(const T& data) const; + std::vector vertices() const; + std::vector neighboursOf(const T& data) const; + std::vector edgesBetween(const T& source, const T& destination) const; + + std::string serialize() const; + + +private: + + + typename std::vector::const_iterator find(const T& data) const; + typename std::vector::iterator find(const T& data); + + std::vector m_vertices; +}; + +// non-member functions + + +// template typename std::vector subtee_breathFirst(const Graph& graph, const T& root); +// template bool connected(const Graph& graph); +// template bool circular(const Graph& graph); +// template typename std::vector path(const Graph& graph, const T& a, const T& b); + + + + +// definitions + + +// Edge + +template +Graph::Edge::Edge(const T& destination, float weight) + : m_destination(&destination) + , m_weight(weight) +{ + +} + +template +Graph::Edge::Edge(const Edge& other) + : m_destination(other.m_destination) + , m_weight(other.m_weight) +{ + +} + +template +typename Graph::Edge& Graph::Edge::operator=(const Edge& other) +{ + if (this != &other) { + m_destination = other.m_destination; + m_weight = other.m_weight; + } + + return *this; +} + + +// Vertex + +template +Graph::Vertex::Vertex(const T& data) + : m_data(&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 T& destination, float weight) +{ + Edge e(destination, weight); + m_edges.push_back(e); +} + +template +void Graph::Vertex::removeEdge(const T& destination, float weight) +{ + m_edges.erase(std::find_if(m_edges.begin(), m_edges.end(), + [&destination, &weight](const Edge& e) + { return e.m_destination == destination && + e.m_weight == weight;})); +} + +template +void Graph::Vertex::removeAllEdgesTo(const T& destination) +{ + std::remove_if(m_edges.begin(), m_edges.end(), + [&destination](const Edge& e) + { return e.m_destination == destination; }); +} + + +// Graph + +template +Graph::Graph() + : m_vertices() +{ + +} + +template +bool Graph::empty() const +{ + return m_vertices.empty(); +} + +template +size_t Graph::numberOfVertices() const +{ + return m_vertices.size(); +} + +template +size_t Graph::numberOfEdges() const +{ + size_t retval = 0; + std::accumulate(m_vertices.begin(), m_vertices.end(), retval, + [](size_t sum, const Vertex& v) + { return sum + v.m_edges.size(); }); + return retval; +} + +template +bool Graph::addVertex(const T& data) +{ + if (find(data) != m_vertices.end()) + return false; + + Vertex v(data); + m_vertices.push_back(v); + return true; +} + +template +bool Graph::removeVertex(const T& 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 T& source, const T& 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 T& source, const T& 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 T& source, const T& 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 T& data) const +{ + return find(data) != m_vertices.end(); +} + +template +std::vector 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 Graph::neighboursOf(const T& 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 Edge& e) + { retval.push_back(e.m_weight); }); + + return retval; +} + +template +std::vector Graph::edgesBetween(const T& source, const T& 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 Edge& e) + { if (e.m_destination == &destination) retval.push_back(e.m_weight); }); + + return retval; +} + + +template +std::string Graph::serialize() const +{ + /// @todo implement me + return std::string(""); +} + +template +typename std::vector::Vertex >::const_iterator Graph::find(const T& 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 T& data) +{ + return std::find_if(m_vertices.begin(), m_vertices.end(), + [&data](const Vertex& v) + { return v.m_data == &data; }); +} + + +/* +template +typename std::vector subtee_breathFirst(const Graph& graph, const T& root) +{ + std::vector retval; + std::vector q; + + q.push_back(root); + while (!q.empty()) { + T node = q.front(); + q.pop_front(); + retval.push_back(node); + + const std::vector neighbours = graph.neighbours(node); + typename std::vector::const_iterator it; + for (it = neighbours.begin(); it != neighbours.end(); ++it) + q.push_back(*it); + } + return retval; +} + +template +bool connected(const Graph& graph) +{ + std::vector connected; + const std::vector vertices = graph.vertices(); + + typename std::vector::const_iterator it; + for (it = vertices.begin(); it != vertices.end(); ++it) { + const std::vector neighbours = graph.neighbours(*it); + typename std::vector::const_iterator it2; + for (it2 = neighbours.begin(); it2 != neighbours.end(); ++it2) + connected.push_back(*it2); + } + + typename std::vector::const_iterator last = std::unique(connected.begin(), connected.end()); + return graph.size == std::distance(connected.begin(), last); +} + +template +bool circular(const Graph& graph) +{ + /// @todo implemente me + return true; +} + + +template +typename std::vector path(const Graph& graph, const T& a, const T& b) +{ + // Dijkstra's algorithm for single-source shortest path + + /// @todo implemente me + return 0; +} +*/ + +#endif // GRAPH_H diff --git a/main.cpp b/main.cpp new file mode 100644 index 0000000..f780036 --- /dev/null +++ b/main.cpp @@ -0,0 +1,41 @@ +#include +#include + + +#include "graph.h" + +int main() +{ + Graph g; + + assert(g.empty() == true); + assert(g.numberOfVertices() == 0); + assert(g.numberOfEdges() == 0); + + + int a = 2; + int b = 5; + assert(g.addEdge(a, b) == false); + + assert(g.addVertex(a) == true); + assert(g.addVertex(a) == false); + assert(g.empty() == false); + assert(g.numberOfVertices() == 1); + + assert(g.addEdge(a, b) == false); + + assert(g.addVertex(b) == true); + assert(g.numberOfVertices() == 2); + + assert(g.numberOfEdges() == 0); + assert(g.addEdge(a, b) == true); + assert(g.numberOfEdges() == 1); + + assert(g.edgesBetween(2, 5).size() == 1); + assert(g.edgesBetween(5, 2).size() == 0); + assert(g.neighboursOf(2).size() == 1); + assert(g.neighboursOf(5).size() == 0); + + return 0; +} +