The Graph ADT
Definition of a Graph
A graph G = (V,E) consists of a set of vertices V and a set of edges E. Each edge is a pair (v,w) where v
and w are vertices. Vertices are sometimes called “nodes”, and edges are sometimes called “arcs.”
If the edges are ordered (indicated with arrows in a picture of a graph), the graph is “directed” and (v,w)
!= (w,v). Directed graphs are also sometimes called “digraphs.”
Edges can also have “weights” or “edge costs” associated with them.
Vertex w is “adjacent” to v if and only if (v,w) is an edge in E.
Very important for real-world problems.
o The airport system is a graph. What is the best flight from one city to another?
o Class prerequisites can be represented as a graph. What is a valid course order?
o Traffic flow can be modeled with a graph. What are the shortest routes?
o Traveling Salesman Problem: What is the best order to visit a list of cities in a graph?
A “path” is a sequence of vertices w1, w2, w3, ..., wn such that (wi, wi+1) are edges in the graph.
The “length” of the path is the number of edges (n-1), where n is the number of vertices in the path.
A “simple” path is one where all vertices are distinct, except perhaps the first and last.
A “cycle” in a directed graph is a path such that the first and last vertices are the same.
A directed graph is “acyclic” if it has no cycles. This is sometimes referred to as a DAG (directed
The previous graph is a DAG.
An undirected graph is “connected” if there is a path from every vertex to every other vertex.
o A directed graph with this property is called “strongly connected.” If the directed graph is not
strongly connected, but the underlying undirected graph is connected, then the graph is “weakly
A “complete” graph is a graph in which there is an edge between every pair of vertices. A graph with
many edges is also called a “dense graph.” In this case, |E| = Ө|V|2.
The prior graphs have been weakly connected and have not been complete.
Might use ∞ for sentinel rather than 0, depending on application.
The adjacency matrix representation requires O(|V|2) space. This is fine if the graph is complete, or
nearly complete. But what if it is sparse (has few edges)?
Then we can save space by using an “adjacency set” or “adjacency list” representation instead. This will
require O(|V|+|E|) space. If we assume that every vertex is in some edge, the number of edges is at least
floor(|V|/2). Hence we may disregard any O(|V|) terms when an O(|E|) term is present. So we say that the
space requirement is O(|E|), or linear in the size of the graph.
A graph is usually constructed from a list of edges.
Vertices that have have names are usually mapped to an internal number ranging from 1 to |V| or from 0
to |V| - 1.
Graph Traversal Algorithms
Also called graph search algorithms.
Two standard methods: breadth-first search and depth-first search.
o The breadth-first search visits vertices in the order of their path length from a starting vertex.
Can be thought of as a generalization of the level-by-level traversal of a binary tree.
o The depth-first search traverses vertices of a graph by making a series of recursive function calls
that follow paths through the graph.
Traversing a graph is similar to traversing a binary tree, except that traversing a graph is a bit more
complicated. Recall that a binary tree has no cycles. Also, starting at the root node, we can traverse the
entire tree. On the other hand, a graph might have cycles and we might not be able to traverse the entire
graph from a single vertex (for example, if the graph is not connected). Therefore, we must keep track of
the vertices that have been visited. We must also traverse the graph from each vertex (that has not been
visited) of the graph. This ensures that the entire graph is traversed.
Depth First Traversal
The depth first traversal is similar to the preorder traversal of a binary tree. The general algorithm for the
recursive version is
for each vertex, v in the graph // Eliminate if
if v is not visited // graph is
start the depth first traversal at v // undirected
The general algorithm to do a depth first traversal at a given node, v, is
mark node v as visited
visit the node
for each vertex u adjacent to v
if u is not visited
start the depth first traversal at u
Breadth First Traversal
The breadth first traversal of a graph is similar to traversing a binary tree level by level (the nodes at each level
are visited from left to right). All nodes at any level, i, are visited before visiting the nodes at level i + 1.
As in the case of depth first traversal, because it might not be possible to traverse the entire graph from a single
vertex, the breadth first traversal also traverses the graph from each vertex that is not visited. Starting at the first
vertex, the graph is traversed as much as possible; we then go to the next vertex that has not yet been visited. To
implement the breadth first search algorithm, we use a queue (it can be implemented recursively, but it’s not
easy). The general algorithm is
for each vertex v in the graph // eliminate if undirected
if v is not visited // eliminate if undirected
add v to the queue
mark v as visited
visit the node
while the queue is not empty
remove vertex u from the queue
for each vertex w that is adjacent to u
if w is not visited
add w to the queue
mark w as visited
visit the node