Today I tried to code up a generic graph abstract data type in C++. Precisely, I implemented the adjacency list data structure for a generic graph type. I think it seems to work with different type according to the test cases I have tried :). Through this post I would like to know what kinds of optimizations can I make to the code to make it more readable, understandable and maintainable and also any kind of performance enhancement pointers are welcomed. The code is as follows for the Graph ADT.
#include<map>
#include<set>
#include<cstdio>
#include<iostream>
#include<iterator>
#include<algorithm>
// this is the structure of a node in our Graph ADT
template<typename T>
struct GraphNode {
T nodeValue;
std :: set< GraphNode<T>* > adjacentNodes;
bool searchPresence(T nodeValue);
};
// this function searches for a node with a specific value if its already present in the adjacency list of "this" node
template<typename T>
bool GraphNode<T> :: searchPresence(T nodeValue) {
typename std :: set< GraphNode<T>* > :: iterator it;
for(it = this->adjacentNodes.begin(); it != this->adjacentNodes.end(); ++it) {
if((*it)->nodeValue == nodeValue)
return true;
}
return false;
}
// this class represents our Graph ADT, which can work irrespective of the data you are working with
template<typename T>
class Graph {
private:
int nVertices;
int nEdges;
bool isDirected;
std :: map<T, GraphNode<T>* > adjacencyListMap;
public:
Graph();
Graph(int nVertices, int nEdges, bool isDirected);
void addEdge(T vertex1, T vertex2);
void displayGraph();
};
// this is the default constructor for the Graph ADT
template<typename T>
Graph<T> :: Graph() {
this->nVertices = 0;
this->nEdges = 0;
this->isDirected = false;
}
// this is the parameterized constructor for the Graph ADT
template<typename T>
Graph<T> :: Graph(int nVertices, int nEdges, bool isDirected) {
this->nVertices = nVertices;
this->nEdges = nEdges;
this->isDirected = isDirected;
}
// this function is used to add an edge to the Graph ADT
template<typename T>
void Graph<T> :: addEdge(T vertex1, T vertex2) {
GraphNode<T>* node1 = new GraphNode<T>();
node1->nodeValue = vertex1;
GraphNode<T>* node2 = new GraphNode<T>();
node2->nodeValue = vertex2;
if(this->adjacencyListMap.find(node1->nodeValue) == this->adjacencyListMap.end()) {
this->adjacencyListMap.insert(std :: pair< T, GraphNode<T>* >(node1->nodeValue, node1));
}
if(!this->adjacencyListMap.find(node1->nodeValue)->second->searchPresence(node2->nodeValue))
this->adjacencyListMap.find(node1->nodeValue)->second->adjacentNodes.insert(node2);
if(this->adjacencyListMap.find(node2->nodeValue) == this->adjacencyListMap.end()) {
this->adjacencyListMap.insert(std :: pair< T, GraphNode<T>* >(node2->nodeValue, node2));
}
if(!this->isDirected) {
if(!this->adjacencyListMap.find(node2->nodeValue)->second->searchPresence(node1->nodeValue))
this->adjacencyListMap.find(node2->nodeValue)->second->adjacentNodes.insert(node1);
}
}
// this function is used to display the graph as an adjacency list
template<typename T>
void Graph<T> :: displayGraph() {
typename std :: map<T, GraphNode<T>*> :: iterator it;
for(it = this->adjacencyListMap.begin(); it != this->adjacencyListMap.end(); ++it) {
std :: cout << (*it).first << " --> ";
typename std :: set< GraphNode<T>* > :: iterator it1;
for(it1 = (*it).second->adjacentNodes.begin(); it1 != (*it).second->adjacentNodes.end(); ++it1)
std :: cout << (*it1)->nodeValue << " -> ";
std :: cout << std :: endl;
}
}
int main() {
bool isDirected;
int nVertices, nEdges;
std :: cout << "Please enter the number of vertices you want in the graph : ";
std :: cin >> nVertices;
std :: cout << "Please enter the number of edges/connections you have in the graph : ";
std :: cin >> nEdges;
std :: cout << "Enter 0 if the graph you want should be undirected and non zero otherwise : ";
std :: cin >> isDirected;
std :: cin.ignore();
Graph<std :: string>* freinds = new Graph<std :: string>(nVertices, nEdges, isDirected);
for(int i = 0; i < nEdges; ++i) {
std :: string node1, node2;
std :: cout << "Edge/Connection #" << i+1 << " - " << std :: endl;
std :: cout << "node 1 : ";
std :: cin >> node1;
std :: cout << "node 2 : ";
std :: cin >> node2;
freinds->addEdge(node1,node2);
}
std :: cout << "The adjacency list representation of the graph you entered is as follows : " << std :: endl;
freinds->displayGraph();
return 0;
}
::
is quite unusual! But since this doesn't qualify as an answer, I'll just rant it here:P
\$\endgroup\$