Adjacency List General
#include <bits/stdc++.h> // Includes common standard libraries like iostream, unordered_map, list.using namespace std; // Use the standard namespace.
// Declare a template for the Graph class.// 'T' is a placeholder for any data type that will represent the vertices (nodes).template <typename T>class Graph {public: // Adjacency list representation using an unordered_map. // Keys are vertices of type T, values are lists of adjacent vertices (also of type T). unordered_map<T, list<T>> adj;
// Function to add an edge between two vertices (u, v). // 'u', 'v': The vertices of type T. // 'direction': false for undirected graph, true for directed graph. void addEdge(T u, T v, bool direction) { // Create an edge from u to v: add v to u's adjacency list. adj[u].push_back(v);
// If the graph is undirected, also add an edge from v to u. if(direction == false) { adj[v].push_back(u); } }
// Function to print the adjacency list of the graph. void printAdjList(){ // Iterate through each key-value pair in the adjacency map. // 'i.first' is the vertex, 'i.second' is its list of neighbors. for(auto i : adj) { cout << i.first << " -> "; // Print the current vertex.
// Iterate through the list of neighbors for the current vertex. for(auto j : i.second) { cout << j << " "; // Print each neighbor. } cout << endl; // Move to the next line for the next vertex. } }};
int main() { int n; // Number of nodes (vertices). int m; // Number of edges.
cout << "Enter the number of nodes : "; cin >> n;
cout << "Enter the number of edges : "; cin >> m;
// Create an instance of the Graph class, specifying 'int' as the type for vertices. Graph<int> G;
// Loop to read 'm' edges from user input. cout << "Enter edges (u v):" << endl; for(int i = 0; i < m; i++) { int u, v; cin >> u >> v; // Read the two vertices (as integers). G.addEdge(u, v, 0); // Add the edge to the graph. '0' indicates an undirected graph. }
// Printing the constructed graph's adjacency list. cout << "\nAdjacency List:" << endl; G.printAdjList();
return 0; // Indicate successful execution.}1. What is a Generic Graph?
- A generic graph allows vertices (nodes) to be represented by data types other than just integers (e.g., characters, strings, custom objects).
- This is achieved using C++ templates, making the
Graphclass reusable for various node types.
2. Adjacency List Representation (Templated)
- Data Structure:
unordered_map<T, list<T>> adjT: This is a template type parameter, meaningTcan be any data type (e.g.,int,char,string, etc.) that supports hashing (forunordered_map) and comparison.unordered_map: Maps a vertex of typeTto a list of its neighbors (also of typeT).list<T>: Represents the list of adjacent vertices for a given key vertex.std::vector<T>orstd::set<T>could also be used, depending on requirements (e.g.,vectorfor better cache locality,setfor sorted unique neighbors,listfor efficient insertions/deletions anywhere).
3. Key Functions & Enhancements
template <typename T>: This syntax declares that theGraphclass (and its methods) will operate on a generic typeT.addEdge(T u, T v, bool direction):- Adds an edge between vertices
uandv. u,vare now of typeT, allowing for flexible node naming.direction:falsefor undirected (addsu-vandv-u),truefor directed (addsu->vonly).
- Adds an edge between vertices
printAdjList(): Iterates through theadjmap and prints each vertex (i.first) and its list of neighbors (i.second). Thecoutstatements will automatically adapt to the typeTifoperator<<is defined forT.
4. Time and Space Complexity (Same as non-templated)
- Space Complexity:
O(V + E)whereVis the number of vertices andEis the number of edges. This holds true as the underlying structure (unordered_mapandlist) scales with the number of vertices and edges, regardless of their data type (assumingThas constant-time copy/move). - Time Complexity:
addEdge():O(1)on average (forunordered_map::operator[]andlist::push_back).printAdjList():O(V + E)because it visits each vertex and each edge once.
5. Benefits of Using Templates
- Reusability: The same
Graphclass can be used for graphs where nodes areint,char,string, or even complex custom objects, without writing separate code for each type. - Type Safety: The compiler ensures type correctness at compile time.
- Flexibility: Adapts to different problem requirements that might use non-integer node identifiers.
6. Usage in main()
Graph<int> G;: When using the templatedGraphclass, you must specify the actual type forTinside angle brackets (e.g.,<int>). You could createGraph<char> G_char;orGraph<string> G_string;if needed.- The rest of the
mainfunction remains similar to the non-templated version, as the input is still read as integers. IfTwerecharorstring,cin >> u >> v;would need to readcharorstringvalues.