LESSON 53 · ADVANCED4 min read

Graph Architectures: Adjacency Lists vs Matrices & BFS/DFS Traversals

Deconstruct graph data structures. Contrast space complexity of Adjacency Lists vs Adjacency Matrices, and implement BFS and DFS traversals with cycle detection.

OpenJDK 21+ (LTS)Free to readModule 14 of 15
YOUR NEXT SMALL WINS

By the end, you’ll be able to…

  • Contrast Adjacency Matrix (O(V^2) space) with Adjacency List (O(V + E) space).
  • Implement Breadth-First Search (BFS) for shortest path in unweighted graphs.
  • Implement Depth-First Search (DFS) for connected components and cycle detection.

01Graph Representations: List vs Matrix

A Graph G = (V, E) consists of a set of Vertices (nodes) connected by Edges (links). Edges can be Directed (one-way) or Undirected (two-way), and Unweighted or Weighted.

There are two primary ways to represent graphs in memory: 1. Adjacency Matrix: A 2D boolean array boolean[V][V]. Edge existence between u and v is checked in instant O(1) time. However, it consumes O(V^2) space. For sparse real-world graphs (e.g. 10 million users with 50 friends each), a matrix would require 100 trillion bytes (100 terabytes)! 2. Adjacency List: An array of lists (List<List<Integer>> or Map<Integer, List<Integer>>). It only stores actual edges, consuming O(V + E) space. In 99% of production applications, Adjacency Lists are standard.

example.js☕Java
Ctrl + ↵
Output
Click Run or press Ctrl+Enter
Output will appear here after you run the code.

02Breadth-First Search (BFS) on Graphs

BFS on a graph visits nodes in concentric rings outward from the source vertex. Because graphs can contain cycles, we must maintain a boolean[] visited array to prevent infinite loops.

Crucially: In any unweighted graph, BFS is mathematically guaranteed to find the Shortest Path (fewest number of edges) from the source to all reachable vertices! As soon as the target vertex is dequeued, its BFS distance is the global minimum.

example.js☕Java
Ctrl + ↵
Output
Click Run or press Ctrl+Enter
Output will appear here after you run the code.

03Depth-First Search (DFS) and Cycle Detection

DFS explores as deeply as possible along each branch before backtracking. In an undirected graph, a cycle exists if DFS encounters a visited neighbor that is NOT the immediate parent of the current node.

In directed graphs, detecting cycles requires tracking recursion stack state: a 3-color state machine (0 = Unvisited, 1 = Visiting/In Stack, 2 = Visited/Completed). If DFS visits a node currently marked as Visiting (1), a Back-Edge exists, proving a cycle.

example.js☕Java
Ctrl + ↵
Output
Click Run or press Ctrl+Enter
Output will appear here after you run the code.

04Why This Matters in Production

Graphs represent interconnected systems: social network follower graphs, recommendation engines, fraud detection rings in banking, and package dependency managers (npm, Maven, Gradle).

Cycle detection ensures build systems do not deadlock on circular dependencies, while BFS shortest-path trees calculate network packet routing in enterprise LANs.

05Production Architecture & Engineering Trade-Offs

Graph algorithms power distributed network routing, dependency resolution, social graph analysis, and transaction fraud ring detection. In production enterprise graphs containing millions of vertices and billions of edges, naive adjacency matrix representations are completely impractical due to quadratic O(V^2) memory consumption.

Adjacency lists or compressed sparse row (CSR) formats are standard because they bound space consumption strictly to O(V + E). When implementing pathfinding algorithms like Dijkstra or A*, choosing the right priority queue implementation (such as 4-ary heaps or pairing heaps) and caching edge weights directly inside CPU cache lines delivers orders-of-magnitude faster convergence on real-world road and transit networks.

LET IT CLICK

The ideas worth keeping.

  • Use Adjacency Lists (O(V + E) space) for sparse graphs instead of Adjacency Matrices (O(V^2)).
  • BFS finds the shortest path in unweighted graphs in linear O(V + E) time.
  • Detect cycles in directed graphs by identifying back-edges with a 3-color DFS state machine.
TURN UNDERSTANDING INTO SOMETHING YOU CAN DO

Make it yours.

Type and test your code right here in the interactive workspace. Run your solution, check the output, and compare with the worked guide when ready.

01

Exercise 1: Number of Connected Components

Write a method countComponents(int n, int[][] edges) that returns the number of connected components in an undirected graph in O(V + E) time.

your_turn_1.java☕Java
Ctrl + ↵
Output
Click Run or press Ctrl+Enter
Output will appear here after you run the code.
Explore a worked solution
one_possible_solution.javaJava
Build adj list. Maintain boolean[] visited. Loop i from 0 to n-1. If !visited[i], run BFS/DFS from i and increment count. Return count.

Each unvisited node initiates a traversal that marks its entire connected component in O(V + E) time.

02

Exercise 2: Clone Graph Deep Copy

Explain how BFS paired with a HashMap<Node, Node> creates a deep copy of an arbitrary graph with cycles in O(V + E) time.

your_turn_2.java☕Java
Ctrl + ↵
Output
Click Run or press Ctrl+Enter
Output will appear here after you run the code.
Explore a worked solution
one_possible_solution.javaJava
Map stores original -> clone mapping. When visiting u, create clone. For each neighbor v, if not in map, create clone and enqueue v. Add cloned v to cloned u's neighbors.

The hash map prevents duplicating nodes and breaking cycle loops during graph cloning.

A SMALL QUESTION. A USEFUL NEXT STEP.

What stayed with you?

Check the ideas while they’re fresh. Your answers stay in this page and feedback appears as you go.

A LITTLE ACTIVE RECALL0 / 3 answered
01What is the space complexity of an Adjacency Matrix versus an Adjacency List for a graph with V vertices and E edges?
02Why is BFS guaranteed to find the shortest path in unweighted graphs?
03How do you detect a cycle in a Directed Graph using DFS?
⚡CODING CHALLENGE
🔒Required to Mark Lesson Complete

Exercise 1: Number of Connected Components

Write a method countComponents(int n, int[][] edges) that returns the number of connected components in an undirected graph in O(V + E) time.

EXPECTED OUTPUT
Build successful. (Java 15)
[Process exited normally]
Main.javaJava
Ctrl + ↵
Execution Console
Click "Run & Verify" (or press Ctrl + Enter) to test your code against the challenge.

Keep exploring.

The official references behind this lesson, when you want a second angle or the full details.

One lesson closer.

Reading is a start. Trying it yourself makes the connection.

Solve the hands-on coding challenge in the knowledge section to verify your code and unlock lesson completion.