## Adjacency List in C++In this article, you will learn about the ## Graph Representation:A graph is a collection of that connect these nodes. Graphs can be categorized into various types, including edges and directed and undirected graphs, weighted and unweighted graphs, cyclic, etc. To perform operations or algorithms on graphs, they need to be represented in a way that computers can efficiently manipulate.acyclic graphs## Adjacency List:An than the maximum possible edges). In an fewer edges, each vertex in the graph is associated with a list of its neighboring vertices. This representation efficiently captures the connectivity of the graph.adjacency listAn , where the number of edges is significantly smaller than the total possible number of edges. In an adjacency list, each vertex in the graph is associated with a list of its neighboring vertices.sparse graphsIn C++, you can implement an adjacency list using various data structures, such as an , or a map from vertices to their neighbors.vector of vectors## Directed Graphs:A , is a type of the graph in which edges have a specific direction, indicating an one-way relationship between vertices. Unlike undirected graphs, where edges represent a connection between vertices without direction, directed graphs capture digraph or dependencies between elements.asymmetric relationshipsIn a and a initial vertex (tail), denoted by an arrow pointing from the terminal vertex (head) to the tail. This arrow indicates the direction of the relationship or flow represented by the edge. This concept of direction gives head a different set of characteristics and behaviors than undirected graphs.directed graphs## Method 1: Using an Array of Lists (or vectors)Let's take an example to understand the adjacency list using an
Vertex 0 has outgoing edges to: 1 3 Vertex 1 has outgoing edges to: 2 Vertex 2 has outgoing edges to: 3 4 Vertex 3 has outgoing edges to: 4 Vertex 4 has outgoing edges to:
- In this example, the
class uses an array of vectors to create the adjacency list. The*DirectedGraph*adds directed edges from the source vertex to the destination vertex. The*addEdge function*displays the adjacency list for each vertex.*printGraph function* - The
indicate the direction of the edges.*arrows* - The numbers inside the vertices correspond to the
.*vertex numbers* - Each vertex points to its outgoing neighbors.
- It represents a
with*directed graph*going from the source vertex to the destination vertex.*directed edges*
0 --> 1 | | v v 3 --> 2 --> 4
- The code defines a
class that models a directed graph using an*directed graph*.*adjacency list* - The class has a private
, to store the number of*member variable, numVertices*and an*vertices*to store the adjacency list.*adjacency list* - The
initializes the*constructor*and resizes the*numVertices*vector to match the number of vertices.*adjacency list* - The
adds directed edges to the graph by pushing the destination vertex into the vector corresponding to the source vertex in the adjacency list.*addEdge method* - The
prints the adjacency list representation. It iterates through each vertex, printing its outgoing neighbors.*printGraph method* - In the
, an instance of*main function*named graph with*DirectedGraph*is created.*5 vertices* - Various edges are added to the graph using the
, defining the directed relationships.*addEdge method* - Finally, the
is called to display the adjacency list representation of the*printGraph method*.*directed graph* - The program's result is the output that shows the adjacency list of the directed graph, indicating which vertices each vertex is connected.
is the number of vertices.V
is the number of vertices and V is the number of edges. It is because it iterates through each vertex and its neighbors.E
is the number of edges since we add edges in the E.main function
vector and each vector inside it for the edges.adjacencyList
and adding edges.graph objectWhere:
.vertices
in the graph.edges## Method 2: Using Map from Vertices to NeighborsLet's take an example to understand the adjacency list using the
Vertex 0 has outgoing edges to: 1 3 Vertex 1 has outgoing edges to: 2 Vertex 2 has outgoing edges to: 3 4 Vertex 3 has outgoing edges to: 4 Here's a visual representation of the
Vertex 0 --> [1] Vertex 1 --> [2] | | v v Vertex 3 --> [4] Vertex 2 --> [3, 4] | v Vertex 4 --> []
- In this example, the code defines a
class that represents a directed graph using a*directed graph*to their neighboring vertices. The map is stored as a private member variable named*map from vertices*.*adjacencyList* - The constructor initializes the number of vertices.
- The
adds a directed edge from the source vertex to the destination vertex by appending the destination to the vector associated with the source vertex key in the adjacency list map.*addEdge function* - The
prints the adjacency list representation of the graph by iterating through the map and displaying the outgoing edges for each vertex.*printGraph function* - In the
, a*main function*object named graph is created with*DirectedGraph*. Edges are added to the graph using*5 vertices*to create the directed graph structure.*addEdge* - After that, the
function is called to display the*printGraph*representation of the graph, showing which vertices each vertex point is connected to.*adjacency list*
is the number of V and vertices is the number of E. It is because it iterates through each vertex and its neighbors.edges
to store vertex mappings.adjacencyList map
is the number of edges in the graph, as we store all edges in the adjacency list.E
Where:
.vertices
in the graph.edges## Undirected Graphs:An that represents a collection of graph theory and vertices (nodes) where the edges do not have a specific direction. In other words, the relationships between vertices are edges (connections) - if an edge connects symmetric to vertex A, it also implies an edge from vertex B to vertex B.vertex A## Method-1: Using an Array of Lists (or vectors)Let's take an example to understand the adjacency list using an
0 is connected to: 1 3 Vertex 1 is connected to: 0 2 Vertex 2 is connected to: 1 3 4 Vertex 3 is connected to: 0 2 4 Vertex 4 is connected to: 2 3 Each The The
- In this example, the code defines a class
**UndirectedGraph**that represents an**undirected graph**using an adjacency list. - The class has a private member
**numVertices**to store the number of vertices and an**adjacency list**to store the adjacency list. - The constructor initializes
**numVertices**and resizes the adjacency list vector to match the number of vertices. - The
**addEdge method**adds an**undirected edge**between two vertices by updating their adjacency lists. - The
**printGraph method**iterates through**vertices**and prints their neighbors, displaying the adjacency list. - An instance of
**UndirectedGraph named**graph with**5 vertices**is created in the**main function**. **Edges**are added using the**addEdge method**to create the connections in the**undirected graph**.- The
**printGraph method**is called to display the adjacency list representation of the graph.
Where:
## Method 2: Using an Array of DequesWe represent an
Vertex 0 is connected to: 1 3 Vertex 1 is connected to: 0 2 Vertex 2 is connected to: 1 3 4 Vertex 3 is connected to: 0 2 4 Vertex 4 is connected to: 2 3
- In this example, the code defines a class named
**UndirectedGraph**to represent an**undirected graph**. - The class includes a private member
**variable, numVertices**, to store the number of vertices in the graph. - The
**adjacency list**is implemented as an array of**deques (double-ended queues)**, where each deque represents a**vertex**in the graph. - The class
**constructor**takes the number of vertices as a**parameter**and initializes the**numVertices variable**. - It dynamically allocates memory for an array of deques, each corresponding to a vertex in the graph.
- The
**addEdge method**allows an**undirected edge**between two vertices (**src**and**dest**). - It pushes integers into the deque associated with the source and destination vertices. This operation ensures the graph is
**undirected**, adding the edge in both directions. - The
**printGraph method**is used to display the adjacency list representation of the graph. - It iterates through each vertex in the graph (from
**0**to**numVertices - 1**) and prints the neighbors stored in the associated deque. - The class includes a destructor to release the dynamically allocated memory for the array of deques when the object is destroyed.
- In the
**main function**, an instance of the**UndirectedGraph class**is created with**5 vertices**. - Several edges are added to the graph using the
**addEdge method**to establish connections between**vertices**. - Finally, the
**printGraph method**displays the adjacency list representation of the undirected graph.
- The
**time complexity**for creating an array of deques is**O(V)**, where V is the number of vertices. - After that, pushing an integer into a
**deque**takes constant time,**O(1)**. - Adding an edge between two vertices (
**src**and**dest**) results in two constant-time operations (one for each direction) for**undirected graphs**. - If there are
**E edges**, the total time complexity for adding edges is**O(E)**. - The method iterates through each
**vertex (V)**and its**neighbors (E),**resulting in a time complexity of**O(V + E)**. - Deleting the array of deques takes
**O(V)**time complexity. - Overall, the
**time complexity**is dominated by adding edges and printing the graph, making it**O(V + E)**.
- The
**space complexity**of the array of deques is**O(V)**, where V is the number of vertices. - Two integers (representing neighbors) are stored for
**each edge**, one in each direction for**undirected graphs**. - If there are
**E edges**, the space complexity for storing integers is**O(2E)**, which simplifies to**O(E)**. - The total
**space complexity**is the sum of the space used by the array of deques and the integers within them, which is**O(V + E)**.
## Method-3: Using Map from Vertices to NeighborsHere's an example of how you can represent an
Vertex 0 is connected to: 1 3 Vertex 1 is connected to: 0 2 Vertex 2 is connected to: 1 3 4 Vertex 3 is connected to: 0 2 4 Vertex 4 is connected to: 2 3
- In this example, the code defines a class named
that represents an*UndirectedGraph*using a map from vertices to their neighbors. It also uses the C++ standard library's*undirected graph*to store neighbors in sorted order.*std::set* - The
in the*addEdge method*class adds*UndirectedGraph*to the graph. It takes two vertex indices,*undirected edges*and*src*, and adds both vertices to each other's adjacency lists using*dest*to ensure that neighbors are stored in sorted order. This way, the same edge is not added multiple times.*std::set* - The
is used to print the adjacency list of the graph. It iterates through each vertex in the*printGraph method*and prints the neighbors associated with each vertex.*adjacency list (adjacency list)* - An instance of the
named graph is created.*UndirectedGraph class* - Several
are added to the graph using the*undirected edges*.*addEdge method* - The
is called to display the adjacency list representation of the graph.*printGraph method* - The code focuses on maintaining a clean adjacency list representation for an undirected graph using a
and*map*of neighbors.*sorted sets*
into a*Inserting elements*takes*std::set*, where*O(log N)*is the number of neighbors for a*N*. Since each*vertex*involves adding two vertices to their respective*edge*, the total*sets*for adding all edges would be*time complexity*, where*O(E * log V)*is the number of*E*and V is the number of vertices.*edges*- This function iterates through each vertex in the adjacency list and its associated neighbors, which takes
, where*O(V + E) time*is the number of*V*and*vertices*is the number of*E*.*edges* - Adding edges takes
time.*O(E * log V)*
The storage of the space complexity:- The space required for the adjacency list is
, where*O(V + E)*is the number of vertices and*V*is the number of edges.*E* - Each set of neighbors uses
, where*O(N) space*is the average number of neighbors for each vertex.*N* - Overall space complexity is
, which simplifies to*O(V + E + V * N)*if the average number of neighbors is not significantly larger than the number of vertices.*O(V + E)*
## Weighted Graph:A ## In a weighted graph:- Each
**edge**has an associated weight representing various quantities such as**distance, cost, time, capacity**, or any other relevant measure. - The weights can be
**positive, negative**, or**zero**, depending on the context and the meaning of the weight. **Weighted graphs**are used to model scenarios where the relationships between nodes have varying levels of**significance, cost**, or**impact**.
For example, consider a scenario where ## Method-1: Using an Array of Lists (or vectors)Here's an example of how you can represent a
Vertex 0 is connected to: 1 (Weight: 2) 3 (Weight: 5) Vertex 1 is connected to: 2 (Weight: 3) Vertex 2 is connected to: 3 (Weight: 1) 4 (Weight: 4) Vertex 3 is connected to: 4 (Weight: 6) Vertex 4 is connected to:
- In this example, the code defines a class named
**WeightedGraph**that represents a**weighted graph**using an array of vectors to store the**adjacency list**. Each element of the adjacency list is a vector containing pairs representing the destination**vertex**and the weight of the**edge**. - The constructor initializes the number of vertices and resizes the adjacency list vector accordingly.
- The
**addEdge method**allows adding**weighted edges**to the graph. It takes the**source vertex, destination vertex**, and**weight**as input. The method appends a pair containing the destination vertex and weight to the vector at the source vertex's position in the**adjacency list**. Additionally, we can uncomment the corresponding line to add the reverse edge for an**undirected graph**. - The
**printGraph method**is used to display the adjacency list representation of the graph. It iterates through each vertex and its associated neighbors (pairs) in the adjacency list and prints the destination vertex along with the weight of the edge. - An instance of the
**WeightedGraph**class named graph is created in the**main function**. Several weighted edges are added to the graph using the a**ddEdge method.**After that, the**printGraph method**is called to display the adjacency list representation of the graph, showing the connections between vertices and the associated edge weights. - This code demonstrates how to represent a
**weighted graph**using an array of vectors and incorporate edge weights into the graph structure.
- Adding an edge involves appending to the adjacency list of the source vertex, which takes
**O(1) time**. - This function iterates through each vertex in the adjacency list and its associated neighbors (pairs), resulting in a time complexity of
**O(V + E)**, where**V**is the number of**vertices**and**E**is the number of**edges**. - Adding edges using the
**addEdge method**takes**O(E) time**.
The space complexity is determined by the storage of the adjacency list and the pairs representing edges: - The space required for the adjacency list is
**O(V + E),**where**V**is the number of vertices and**E**is the number of edges. - Each pair representing an edge uses
**O(1) space**. - Overall space complexity is
**O(V + E)**due to the adjacency list and the pairs.
Where:
## Method 2: Using Map from Vertices to NeighborsHere's an example of how you can represent a
Vertex 0 is connected to: 1 (Weight: 2) 3 (Weight: 5) Vertex 1 is connected to: 2 (Weight: 3) Vertex 2 is connected to: 3 (Weight: 1) 4 (Weight: 4) Vertex 3 is connected to: 4 (Weight: 6)
- In this example, the code defines a class named
**WeightedGraph**that represents a**weighted graph**using a map from vertices to neighbors, where each neighbor is associated with a weight. - The
**addEdge method**allows adding**weighted edges**to the graph. It takes the**source vertex, destination vertex**, and**weight**as input. The method updates the inner map associated with the**source vertex**to include the**destination vertex**as a neighbor, along with the weight of the edge. You can uncomment the corresponding line to add the**reverse edge**for an**undirected graph**. - The
**printGraph method**is used to display the**adjacency list**representation of the graph. It iterates through each vertex in the**outer map**and its associated**neighbors (inner map)**to print the destination vertex and the weight of the edge.
- An instance of the
**WeightedGraph**class named graph is created. - Several weighted edges are added to the graph using the
**addEdge method**. - After that, the
**printGraph method**is called to display the**adjacency list**representation of the graph, showing the connections between vertices and the associated edge weights.
- Adding an edge involves updating the
**inner map**associated with the source vertex, which takes**O(log N) time**, where**N**is the average number of neighbors for a vertex. - This function iterates through each vertex in the
**adjacency list**and its associated neighbors (**inner map**), resulting in a time complexity of**O(V + E),**where**V**is the number of vertices and**E**is the number of edges. - Adding edges using the
**addEdge**method takes**O(E * log N) time**.
The space complexity is determined by the storage of the adjacency list and the maps representing edges: - The space required for the adjacency list is
**O(V + E)**, where**V**is the number of vertices and**E**is the number of edges. - Each inner map associated with a vertex uses
**O(N) space**, where**N**is the average number of neighbors for a vertex. - Overall space complexity is
**O(V + E + V * N),**which simplifies to**O(V + E + E * log N)**or simply**O(V + E)**if**N**is not significantly larger than the number of vertices.
## Method-3: Using an Array of DequesWe represent a
Vertex 0 is connected to: 1 (Weight: 2) 3 (Weight: 5) Vertex 1 is connected to: 0 (Weight: 2) 2 (Weight: 3) Vertex 2 is connected to: 1 (Weight: 3) 3 (Weight: 1) 4 (Weight: 4) Vertex 3 is connected to: 0 (Weight: 5) 2 (Weight: 1) 4 (Weight: 6) Vertex 4 is connected to: 2 (Weight: 4) 3 (Weight: 6)
- In this example, the code defines a class named
**weighted graph**to represent a weighted graph. - It includes a private member
**variable, numVertices**, to store the number of vertices in the graph. - The class
**constructor**takes the number of vertices as a**parameter**and initializes the**numVertices variable**. - It dynamically allocates memory for an array of
**deques**, each corresponding to a vertex in the graph. - The
**adjacency list**is implemented as an array of**deques**containing pairs of integers. Each pair consists of the**neighbor vertex**and the weight of the edge connecting the**current vertex**to that neighbor. - The
**addEdge method**allows adding a**weighted edge**between two vertices (**src**and**dest**) with a specified weight. - It pushes a pair into the deque associated with the source and destination vertices. This pair includes the
**neighbor vertex (dest)**and the edge weight connecting the**current vertex (src)**to that neighbor. - For
**undirected graphs,**it also adds the reverse edge to ensure symmetric relationships between vertices. - The
**printGraph method**is used to display the adjacency list representation of the graph. - It iterates through each vertex in the graph (from
**0**to**numVertices - 1**) and prints the neighbors and their associated edge weights. - The class includes a
**destructor**to release the dynamically allocated memory for the array of deques when the object is destroyed. - In the main function, an instance of the
**WeightedGraph**class is created, and several weighted edges are added to the graph using the**addEdge method**. Finally, the**printGraph method**is called to display the adjacency list representation of the graph, including the vertices, their neighbors, and edge weights. - This code provides a clear and efficient representation of a weighted graph using an array of deques. It is suitable for various applications where weighted edges and efficient neighbor traversal are essential.
- The time complexity for creating an array of deques is
**O(V)**, where V is the number of vertices. - Pushing a pair into a deque takes constant time,
**O(1)**. - Adding an edge between two vertices results in two constant-time operations for
**undirected graphs**. - If there are
**E edges**, the total time complexity for**adding edges**is**O(E)**. - The method iterates through each vertex and its neighbors, resulting in a time complexity of
**O(V + E),**where**V**is the number of vertices, and E is the number of edges. - Deleting the array of deques takes
**O(V).** - Therefore, the time complexity is dominated by adding edges and printing the graph, making it
**O(V + E)**.
- The space complexity of the array of deques is
**O(V)**, where V is the number of vertices. - A pair (
**neighbor vertex, edge weight**) is stored twice for undirected graphs for each edge. - If there are
**E edges**, the space complexity for storing pairs is**O(2E)**, which simplifies to**O(E).** - The total space complexity is the sum of the space used by the array of deques and the pairs in the deques, which is
**O(V + E)**.
## Applications of Adjacency lists:
## Benefits:
## Limitations:
Next TopicMake_pair in C++ |