#ifndef GRAPH_H #define GRAPH_H #include "Edge.h" #include "Tree.h" #include #include using namespace std; template class Graph { public: /** Construct an empty graph */ Graph(); /** Construct a graph from vertices in a vector and * edges in 2-D array */ Graph(vector vertices, int edges[][2], int numberOfEdges); /** Construct a graph with vertices 0, 1, ..., n-1 and * edges in 2-D array */ Graph(int numberOfVertices, int edges[][2], int numberOfEdges); /** Construct a graph from vertices and edges objects */ Graph(vector vertices, vector edges); /** Construct a graph with vertices 0, 1, ..., n-1 and * edges in a vector */ Graph(int numberOfVertices, vector edges); /** Return the number of vertices in the graph */ int getSize() const; /** Return the degree for a specified vertex */ int getDegree(int v) const; /** Return the vertex for the specified index */ T getVertex(int index) const; /** Return the index for the specified vertex */ int getIndex(T v) const; /** Return the vertices in the graph */ vector getVertices() const; /** Return the neighbors of vertex v */ vector getNeighbors(int v) const; /** Print the edges */ void printEdges() const; /** Print the adjacency matrix */ void printAdjacencyMatrix() const; /** Obtain a depth-first search tree */ /** To be discussed in Section 24.7 */ Tree dfs(int v) const; /** Starting bfs search from vertex v */ /** To be discussed in Section 24.7 */ Tree bfs(int v) const; protected: vector vertices; // Store vertices vector< vector > neighbors; // Adjacency lists private: /** Create adjacency lists for each vertex from an edge array */ void createAdjacencyLists(int numberOfVertices, int edges[][2], int numberOfEdges); /** Create adjacency lists for each vertex from an Edge vector */ void createAdjacencyLists(int numberOfVertices, vector &edges); /** Recursive function for DFS search */ void dfs(int v, vector &parent, vector &searchOrders, vector &isVisited) const; }; template Graph::Graph() { } template Graph::Graph(vector vertices, int edges[][2], int numberOfEdges) { this->vertices = vertices; createAdjacencyLists(vertices.size(), edges, numberOfEdges); } template Graph::Graph(int numberOfVertices, int edges[][2], int numberOfEdges) { for (int i = 0; i < numberOfVertices; i++) vertices.push_back(i); // vertices is {0, 1, 2, ..., n-1} createAdjacencyLists(numberOfVertices, edges, numberOfEdges); } template Graph::Graph(vector vertices, vector edges) { this->vertices = vertices; createAdjacencyLists(vertices.size(), edges); } template Graph::Graph(int numberOfVertices, vector edges) { for (int i = 0; i < numberOfVertices; i++) vertices.push_back(i); // vertices is {0, 1, 2, ..., n-1} createAdjacencyLists(numberOfVertices, edges); } template void Graph::createAdjacencyLists(int numberOfVertices, int edges[][2], int numberOfEdges) { for (int i = 0; i < numberOfVertices; i++) { neighbors.push_back(vector(0)); } for (int i = 0; i < numberOfEdges; i++) { int u = edges[i][0]; int v = edges[i][1]; neighbors[u].push_back(v); } } template void Graph::createAdjacencyLists(int numberOfVertices, vector &edges) { for (int i = 0; i < numberOfVertices; i++) { neighbors.push_back(vector(0)); } for (int i = 0; i < edges.size(); i++) { int u = edges[i].u; int v = edges[i].v; neighbors[u].push_back(v); } } template int Graph::getSize() const { return vertices.size(); } template int Graph::getDegree(int v) const { return neighbors[v].size(); } template T Graph::getVertex(int index) const { return vertices[index]; } template int Graph::getIndex(T v) const { for (int i = 0; i < vertices.size(); i++) { if (vertices[i] == v) return i; } return -1; // If vertex is not in the graph } template vector Graph::getVertices() const { return vertices; } template vector Graph::getNeighbors(int v) const { return neighbors[v]; } template void Graph::printEdges() const { for (int u = 0; u < neighbors.size(); u++) { cout << "Vertex " << u << ": "; for (int j = 0; j < neighbors[u].size(); j++) { cout << "(" << u << ", " << neighbors[u][j] << ") "; } cout << endl; } } template void Graph::printAdjacencyMatrix() const { int size = vertices.size(); // Use vector for 2-D array vector< vector > adjacencyMatrix(size); // Initialize 2-D array for adjacency matrix for (int i = 0; i < size; i++) { adjacencyMatrix[i] = vector(size); } for (int i = 0; i < neighbors.size(); i++) { for (int j = 0; j < neighbors[i].size(); j++) { int v = neighbors[i][j]; adjacencyMatrix[i][v] = 1; } } for (int i = 0; i < adjacencyMatrix.size(); i++) { for (int j = 0; j < adjacencyMatrix[i].size(); j++) { cout << adjacencyMatrix[i][j] << " "; } cout << endl; } } template Tree Graph::dfs(int v) const { vector searchOrders; vector parent(vertices.size()); for (int i = 0; i < vertices.size(); i++) parent[i] = -1; // Initialize parent[i] to -1 // Mark visited vertices vector isVisited(vertices.size()); for (int i = 0; i < vertices.size(); i++) { isVisited[i] = false; } // Recursively search dfs(v, parent, searchOrders, isVisited); // Return a search tree return Tree(v, parent, searchOrders); } template void Graph::dfs(int v, vector &parent, vector &searchOrders, vector &isVisited) const { // Store the visited vertex searchOrders.push_back(v); isVisited[v] = true; // Vertex v visited for (int j = 0; j < neighbors[v].size(); j++) { int i = neighbors[v][j]; if (!isVisited[i]) { parent[i] = v; // The parent of vertex i is v dfs(i, parent, searchOrders, isVisited); // Recursive search } } } template Tree Graph::bfs(int v) const { vector searchOrders; vector parent(vertices.size()); for (int i = 0; i < vertices.size(); i++) parent[i] = -1; // Initialize parent[i] to -1 queue queue; // list used as a queue vector isVisited(vertices.size()); queue.push(v); // Enqueue v isVisited[v] = true; // Mark it visited while (!queue.empty()) { int u = queue.front(); // Get the top element queue.pop(); // remove the top element searchOrders.push_back(u); // u searched for (int j = 0; j < neighbors[u].size(); j++) { int w = neighbors[u][j]; if (!isVisited[w]) { queue.push(w); // Enqueue w parent[w] = u; // The parent of w is u isVisited[w] = true; // Mark it visited } } } return Tree(v, parent, searchOrders); } #endif