Adjacency List

About

The Adjacency List is one of the most efficient ways to represent a graph, especially when dealing with sparse graphs (i.e., graphs with fewer edges compared to the number of vertices).

Instead of using a 2D matrix (which consumes O(V^2) space), an Adjacency List stores only the relevant edges for each vertex, leading to a space complexity of O(V+E).

Structure

Each vertex in the graph has a list of adjacent vertices (neighbors). The adjacency list can be implemented using:

  1. Array of Linked Lists (Traditional Approach)

  2. HashMap (Dictionary) of Lists (For unordered graphs)

  3. Array of Dynamic Arrays (ArrayList)

Each entry in the adjacency list contains:

  • The vertex

  • A list of its adjacent vertices (or tuples containing adjacent vertex and weight in weighted graphs)

Implementation using an Array of Lists

Code

import java.util.*;

class Graph {
    private int vertices; // Number of vertices
    private LinkedList<Integer>[] adjacencyList; // Adjacency List

    // Constructor
    public Graph(int vertices) {
        this.vertices = vertices;
        adjacencyList = new LinkedList[vertices];

        // Initialize each adjacency list as an empty list
        for (int i = 0; i < vertices; i++) {
            adjacencyList[i] = new LinkedList<>();
        }
    }

    // Method to add an edge (Undirected Graph)
    public void addEdge(int src, int dest) {
        adjacencyList[src].add(dest);
        adjacencyList[dest].add(src); // For an undirected graph
    }

    // Method to remove an edge
    public void removeEdge(int src, int dest) {
        adjacencyList[src].remove(Integer.valueOf(dest));
        adjacencyList[dest].remove(Integer.valueOf(src)); // Undirected Graph
    }

    // Method to check if an edge exists
    public boolean hasEdge(int src, int dest) {
        return adjacencyList[src].contains(dest);
    }

    // Method to get neighbors of a vertex
    public List<Integer> getNeighbors(int vertex) {
        return adjacencyList[vertex];
    }

    // Method to perform Breadth-First Search (BFS)
    public void bfs(int startVertex) {
        boolean[] visited = new boolean[vertices];
        Queue<Integer> queue = new LinkedList<>();
        
        visited[startVertex] = true;
        queue.add(startVertex);

        System.out.print("BFS Traversal: ");
        while (!queue.isEmpty()) {
            int vertex = queue.poll();
            System.out.print(vertex + " ");

            for (int neighbor : adjacencyList[vertex]) {
                if (!visited[neighbor]) {
                    visited[neighbor] = true;
                    queue.add(neighbor);
                }
            }
        }
        System.out.println();
    }

    // Method to perform Depth-First Search (DFS)
    public void dfs(int startVertex) {
        boolean[] visited = new boolean[vertices];
        System.out.print("DFS Traversal: ");
        dfsHelper(startVertex, visited);
        System.out.println();
    }

    private void dfsHelper(int vertex, boolean[] visited) {
        visited[vertex] = true;
        System.out.print(vertex + " ");

        for (int neighbor : adjacencyList[vertex]) {
            if (!visited[neighbor]) {
                dfsHelper(neighbor, visited);
            }
        }
    }

    // Method to print adjacency list representation
    public void printGraph() {
        for (int i = 0; i < vertices; i++) {
            System.out.print("Vertex " + i + " -> ");
            for (Integer neighbor : adjacencyList[i]) {
                System.out.print(neighbor + " ");
            }
            System.out.println();
        }
    }

    public static void main(String[] args) {
        Graph graph = new Graph(5);
        
        graph.addEdge(0, 1);
        graph.addEdge(0, 4);
        graph.addEdge(1, 2);
        graph.addEdge(1, 3);
        graph.addEdge(1, 4);
        graph.addEdge(2, 3);
        graph.addEdge(3, 4);

        graph.printGraph();

        // Test Edge Existence
        System.out.println("Edge 1-3 exists? " + graph.hasEdge(1, 3)); // True
        System.out.println("Edge 2-4 exists? " + graph.hasEdge(2, 4)); // False

        // Remove an Edge and Print Again
        graph.removeEdge(1, 4);
        System.out.println("Graph after removing edge (1,4):");
        graph.printGraph();

        // Get Neighbors of a Vertex
        System.out.println("Neighbors of vertex 1: " + graph.getNeighbors(1));

        // Perform BFS and DFS
        graph.bfs(0);
        graph.dfs(0);
    }
}

Output

Time Complexity Analysis

Operation
Time Complexity

Add an Edge

O(1)

Remove an Edge

O(V) (worst case)

Check Edge Exists

O(V) (worst case)

Get Neighbours

O(1)

BFS Traversal

O(V+E)

DFS Traversal

O(V+E)

Weighted Graph Implementation (Using HashMap)

If the graph is weighted, each edge stores an additional weight value. This can be implemented using a HashMap of Lists, where each list contains pairs of (neighbour, weight).

Code

Output

Time Complexity Analysis

Operation
Time Complexity

Add an Edge

O(1)

Remove an Edge

O(1)

Check Edge Exists

O(1)

Get Edge Weight

O(1)

Get Neighbors

O(1)

BFS Traversal

O(V+E)

DFS Traversal

O(V+E)

Last updated