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
Graph
class reusable for various node types.
2. Adjacency List Representation (Templated)
- Data Structure:
unordered_map<T, list<T>> adj
T
: This is a template type parameter, meaningT
can be any data type (e.g.,int
,char
,string
, etc.) that supports hashing (forunordered_map
) and comparison.unordered_map
: Maps a vertex of typeT
to 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.,vector
for better cache locality,set
for sorted unique neighbors,list
for efficient insertions/deletions anywhere).
3. Key Functions & Enhancements
template <typename T>
: This syntax declares that theGraph
class (and its methods) will operate on a generic typeT
.addEdge(T u, T v, bool direction)
:- Adds an edge between vertices
u
andv
. u
,v
are now of typeT
, allowing for flexible node naming.direction
:false
for undirected (addsu-v
andv-u
),true
for directed (addsu->v
only).
- Adds an edge between vertices
printAdjList()
: Iterates through theadj
map and prints each vertex (i.first
) and its list of neighbors (i.second
). Thecout
statements will automatically adapt to the typeT
ifoperator<<
is defined forT
.
4. Time and Space Complexity (Same as non-templated)
- Space Complexity:
O(V + E)
whereV
is the number of vertices andE
is the number of edges. This holds true as the underlying structure (unordered_map
andlist
) scales with the number of vertices and edges, regardless of their data type (assumingT
has 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
Graph
class 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 templatedGraph
class, you must specify the actual type forT
inside angle brackets (e.g.,<int>
). You could createGraph<char> G_char;
orGraph<string> G_string;
if needed.- The rest of the
main
function remains similar to the non-templated version, as the input is still read as integers. IfT
werechar
orstring
,cin >> u >> v;
would need to readchar
orstring
values.