CS205 Data Structures
Use arrow keys or buttons to navigate • 20 slides
A graph G = (V, E) consists of:
Each edge connects two vertices. Unlike trees, graphs have no root, no parent-child hierarchy, and can contain cycles.
People are vertices. Friendships are edges. You can reach anyone through a chain of mutual friends — that is a path in the graph.
Intersections are vertices. Roads connecting them are edges. Distances are weights on those edges.
Graphs are the most general data structure for modeling relationships. Trees, linked lists, and even arrays are all special cases of graphs!
| Term | Definition |
|---|---|
| Vertex (Node) | A fundamental unit in a graph |
| Edge | A connection between two vertices |
| Adjacent | Two vertices connected by an edge |
| Incident | An edge is incident to its endpoints |
| Degree | Number of edges touching a vertex |
| Path | Sequence of vertices connected by edges |
| Cycle | A path that starts and ends at the same vertex |
| Connected | Every vertex is reachable from every other |
| Component | A maximal connected subgraph |
The degree of a vertex is the most fundamental local property. It tells you how "connected" that vertex is.
Edges have no direction. If A connects to B, then B connects to A.
Examples: Facebook friendships, road networks (two-way streets), computer networks (Ethernet)
Edges have a direction. An edge from A to B does NOT imply B to A.
Examples: Twitter follows, one-way streets, web page hyperlinks, prerequisite courses
Undirected = two-way street: you can drive in both directions. Directed = one-way street: traffic flows in only one direction. Violating the direction is illegal (and impossible in graphs)!
All edges are "equal" — there is no cost associated with traversing an edge.
Each edge carries a weight (cost, distance, time, capacity, etc.).
Weights let us model real-world costs. The "shortest path" in a weighted graph minimizes total weight, not number of edges.
Every vertex connects to every other vertex.
Vertices split into two sets; edges only cross between sets.
Directed graph with no cycles. Used for dependencies.
A connected, acyclic, undirected graph.
A Graph ADT defines the operations we need, independent of representation.
| Method | Description |
|---|---|
vertices() | Return all vertices |
edges() | Return all edges |
numVertices() | Return |V| |
numEdges() | Return |E| |
getEdge(u, v) | Return edge from u to v (or null) |
degree(v) | Number of edges incident to v |
adjacentVertices(v) | Return neighbors of v |
| Method | Description |
|---|---|
insertVertex(x) | Add a new vertex with element x |
insertEdge(u, v, x) | Add edge between u and v with element x |
removeVertex(v) | Remove vertex v and all its edges |
removeEdge(e) | Remove edge e |
The ADT tells us what operations a graph supports. The representation (matrix, list, or edge list) determines how efficiently each operation runs.
A 2D array A[V][V] where A[i][j] = 1 if there is an edge from vertex i to vertex j.
Space: O(V2) regardless of how many edges exist. For a graph with 10,000 vertices, this matrix has 100,000,000 cells!
Store the weight instead of 1, and use infinity (or a sentinel) instead of 0 for non-edges.
A[i][j]A[i][j]Use when the graph is dense (many edges), when you need constant-time edge lookup, or when V is small enough that O(V2) space is acceptable.
An array of lists. Each vertex stores a list of its neighbors.
Space: O(V + E). We store each edge exactly twice (once in each endpoint's list) for undirected graphs. Much better than O(V2) for sparse graphs!
Each person (vertex) has their own phone contact list (linked list of neighbors). You only store contacts you actually have, not a slot for every person on Earth.
Most real-world graphs are sparse (|E| much less than V2), so adjacency lists are the default choice for graph representation in practice.
Side-by-side comparison for the same graph:
| Operation | Adjacency Matrix | Adjacency List |
|---|---|---|
| Space | O(V2) | O(V + E) |
| Check edge (u,v) | O(1) | O(min(deg(u), deg(v))) |
| Add edge | O(1) | O(1) |
| Remove edge | O(1) | O(deg(u)) |
| Iterate neighbors of v | O(V) | O(deg(v)) |
| Add vertex | O(V2) | O(1) |
| Best for | Dense graphs | Sparse graphs |
If |E| is close to V2 → use matrix. If |E| is much less than V2 → use list. Most real-world graphs are sparse, so adjacency list is the default.
The simplest representation: just store a list of all edges as (u, v) pairs.
| Operation | Cost |
|---|---|
| Space | O(E) |
| Check edge (u,v) | O(E) — must scan list |
| Add edge | O(1) — append to list |
| Remove edge | O(E) — must find it |
| Iterate neighbors | O(E) — must scan all |
When you need to process all edges (e.g., Kruskal's MST algorithm), or when the graph is very simple and you want minimal overhead.
Edge lists are slow for lookups. You cannot quickly check if a specific edge exists or find a vertex's neighbors. Use adjacency list or matrix for general-purpose graphs.
Sum of all vertex degrees = 2 × |E|
Each edge contributes 1 to the degree of each of its two endpoints, so it is counted twice in the sum.
A connected component is a maximal set of vertices where every pair is connected by a path.
Twitter/Instagram: You can follow someone without them following you back. This is a directed graph. In-degree = followers. Out-degree = following.
Internet routing is fundamentally a shortest-path problem on a weighted graph. Protocols like OSPF use Dijkstra's algorithm!
Physical Internet: undirected, weighted (bandwidth). World Wide Web: directed, unweighted (hyperlinks). Same real-world system, two different graph models!
Every time you use Google Maps or GPS navigation, you are running a shortest-path algorithm on a massive weighted graph with millions of vertices.
Now that you understand graph structure, here is what is coming next:
| Matrix | Adj List | Edge List | |
|---|---|---|---|
| Space | O(V2) | O(V+E) | O(E) |
| Check edge | O(1) | O(deg) | O(E) |
| Add edge | O(1) | O(1) | O(1) |
| Neighbors | O(V) | O(deg) | O(E) |
| Best for | Dense | Sparse | Edge-proc |
Graphs model connections. Choose your representation based on graph density and which operations you need most. Adjacency list is the go-to default for most real-world problems.
BFS, DFS, shortest paths, and topological sort — algorithms that unlock the true power of graphs.