#ifndef _DIGRAPH_H #define _DIGRAPH_H #include #include "Array.h" #include "Hash.h" #include "test_utilities.h" // directed graph // // restriction: from any vertex u to any vertex w there is at most one edge class Digraph { public: ~Digraph(); // destructor Digraph(); // constructor Digraph(const Digraph & g); // copy constructor int add_vertex(); // adds vertex, returns integer id for vertex int add_vertex(int id); // adds vertex using given id (if not already there) void add_edge(int from, int to); // adds edge, vertices from and to must already exist int edge_exists(int from, int to) const; // return whether exists edge from "from" to "to" int vertex_exists(int v) const; // is there a vertex with id v void remove_vertex(int v); // remove any vertex with id v void remove_edge(int from, int to); // remove from "from" to "to" Array vertices() const; // return array of vertex ids in graph Array out_nbrs(int v) const; // return array of ids of out-neighbors Array in_nbrs(int v) const; // return array of ids of in-neighbors void clear(); // make graph empty (no vertices, no edges) Digraph& operator=(const Digraph& g); // assignment operator friend std::ostream& operator<<(std::ostream& out, const Digraph & g); private: int next_vertex_id; HashTable > ids_of_out_nbrs; // vertex ids of out neighbors HashTable > ids_of_in_nbrs; // vertex ids of in neighbors }; std::ostream& operator<<(std::ostream& out, const Digraph & g) { Array _vertices = g.vertices(); for (int i = 0; i < _vertices.size(); ++i) { int v_id = _vertices[i]; out << v_id << ":"; Array _out_nbrs = g.out_nbrs(v_id); for (int j = 0; j < _out_nbrs.size(); ++j) out << " " << _out_nbrs[j]; out << std::endl; } return out; } Digraph::~Digraph() { } Digraph::Digraph() : next_vertex_id(0) { } Digraph::Digraph(const Digraph & g) : next_vertex_id(g.next_vertex_id), ids_of_out_nbrs(g.ids_of_out_nbrs), ids_of_in_nbrs(g.ids_of_in_nbrs) { } int Digraph::vertex_exists(int v) const { return ids_of_out_nbrs.exists(v); } int Digraph::edge_exists(int from, int to) const { return vertex_exists(from) && ids_of_out_nbrs[from].exists(to); } Array Digraph::out_nbrs(int v) const { if (vertex_exists(v)) return ids_of_out_nbrs[v].keys(); die("Digraph::out_nbrs called with non-existent vertex"); } Array Digraph::in_nbrs(int v) const { if (vertex_exists(v)) return ids_of_in_nbrs[v].keys(); die("Digraph::in_nbrs called with non-existent vertex"); } int Digraph::add_vertex() { int id = next_vertex_id++; ids_of_out_nbrs[id]; ids_of_in_nbrs[id]; return id; } int Digraph::add_vertex(int id) { if (id >= next_vertex_id) next_vertex_id = id+1; ids_of_out_nbrs[id]; ids_of_in_nbrs[id]; return id; } void Digraph::add_edge(int from, int to) { if (vertex_exists(from) && vertex_exists(to)) { ids_of_out_nbrs[from][to] = 1; ids_of_in_nbrs[to][from] = 1; } else die("Digraph::add_edge called with non-existent vertex"); } void Digraph::remove_edge(int from, int to) { if (vertex_exists(from) && vertex_exists(to)) { ids_of_out_nbrs[from].remove(to); ids_of_in_nbrs[to].remove(from); } else std::cerr << "Warning: Digraph::remove_edge called with non-existent vertex" << std::endl; } void Digraph::remove_vertex(int v) { if (vertex_exists(v)) { Array _out_nbrs = out_nbrs(v); Array _in_nbrs = in_nbrs(v); for (int i = 0; i < _out_nbrs.size(); ++i) remove_edge(v, _out_nbrs[i]); for (int i = 0; i < _in_nbrs.size(); ++i) remove_edge(_in_nbrs[i], v); ids_of_out_nbrs.remove(v); ids_of_in_nbrs.remove(v); } else std::cerr << "Warning: Digraph::remove_vertex called with non-existent vertex" << std::endl; } Array Digraph::vertices() const { return ids_of_out_nbrs.keys(); } void Digraph::clear() { next_vertex_id = 1; ids_of_out_nbrs.clear(); ids_of_in_nbrs.clear(); } Digraph& Digraph::operator=(const Digraph& g) { // assignment operator next_vertex_id = g.next_vertex_id; ids_of_out_nbrs = g.ids_of_out_nbrs; ids_of_in_nbrs = g.ids_of_in_nbrs; } #endif