CHAPTER 7 - C++ Graphs
CHAPTER 7 - C++ Graphs
C++ Graphs
LESSON 7.1
Introduction to Graphs
In previous chapters, you learned various ways to represent and manipulate data.
This chapter discusses how to implement and manipulate graphs, which have
numerous applications in computer science.
The river has four land areas (A, B, C, D), as shown in the figure. These
land areas are connected using seven bridges, as shown in Figure 7.1.1. The
bridges are labeled a, b, c, d, e, f, and g. The Ko¨nigsberg bridge problem is as
follows: Starting at one land area, is it possible to walk across all the bridges
exactly once and return to the starting land area?
Over the past 200 years, graph theory has been applied to a variety of
applications. Graphs are used to model electrical circuits, chemical compounds,
highway maps, and so on. They are also used in the analysis of electrical circuits,
finding the shortest route, project planning, linguistics, genetics, social science,
and so forth. In this chapter, you learn about graphs and their applications in
computer science.
A graph G is a pair, G = (V, E), where V is a finite nonempty set, called the
set of vertices of G and E ⊆ V x V . That is, the elements of E are pairs of elements
of V. E is called the set of edges of G. G is called trivial if it has only one vertex.
Let V(G) denote the set of vertices, and E(G) denote the set of edges of a
graph G. If the elements of E are ordered pairs, G is called a directed graph or
digraph; otherwise, G is called an undirected graph. In an undirected graph, the
pairs (u, v) and (v, u) represent the same edge.
A graph can be shown pictorially. The vertices are drawn as circles, and a
label inside the circle represents the vertex. In an undirected graph, the edges are
drawn using lines. In a directed graph, the edges are drawn using arrows.
V(G1) = {1, 2, 3, 4, 5} E(G1) = {(1, 2), (1, 4), (2, 5), (3, 1), (3, 4),
(4, 5)}
V(G2) = {0, 1, 2, 3, 4} E(G2) = {(0, 1), (0, 3), (1, 2), (1, 4), (2, 1),
(2, 4), (4, 3)}
V(G3) = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10} E(G3) = {(0, 1), (0, 5), (1, 2), (1, 3), (1, 5),
(2, 4), (4, 3), (5, 6), (6, 8), (7, 3), (7, 8), (8,
10), (9, 4), (9, 7), (9, 10)}
Let G be an undirected graph. Let u and v be two vertices in G. Then u and v are
called adjacent if there is an edge from one to the other; that is, (u, v) ∈ E. An
edge incident on a single vertex is called a loop. If two edges, e1 and e2, are
associated with the same pair of vertices {u, v}, then e1 and e2 are called parallel
edges. A graph is called a simple graph if it has no loops and no parallel edges. Let
e = (u, v) be an edge in G. We then say that edge e is incident on the vertices u
and v. The degree of u, written deg(u) or d(u), is the number of edges incident
with u. We make the convention that each loop on a vertex u contributes 2 to the
degree of u. u is called an even (odd) degree vertex if the degree of u is even
(odd). There is a path from u to v if there is a sequence of vertices u1, u2, . . ., un
such that u = u1, un = v and (ui , ui+ 1) is an edge for all i = 1, 2, . . ., n - 1. Vertices
u and v are called connected if there is a path from u to v. A simple path is a path
in which all the vertices, except possibly the first and last vertices, are distinct. A
cycle in G is a simple path in which the first and last vertices are the same. G is
called connected if there is a path from any vertex to any other vertex. A maximal
subset of connected vertices is called a component of G.
Adjacency Matrices
Let G be a graph with n vertices, where n > 0. Let V(G) = {v1, v2, . . ., vn}. The
adjacency matrix AG is a two-dimensional n x n matrix such that the (i, j)th entry
of AG is 1 if there is an edge from vi to vj ; otherwise, the (i, j)th entry is 0. That is,
In an undirected graph, if (vi , vj ) ∈ E(G), then (vj , vi) ∈ E(G), so AG(i, j) = 1 = AG(
j, i). It follows that the adjacency matrix of an undirected graph is symmetric.
Consider the directed graphs of Figure 7.1.4. The adjacency matrices of the
directed graphs G1 and G2 are as follows:
Adjacency Lists
Let G be a graph with n vertices, where n > 0. Let V(G) = {v1, v2, . . ., vn}. In the
adjacency list representation, corresponding to each vertex, v, there is a linked
list such that each node of the linked list contains the vertex, u, such that (v, u) ∈
E(G). Because there are n nodes, we use an array, A, of size n, such that A[i] is a
reference variable pointing to the first node of the linked list containing the
vertices to which vi is adjacent. Clearly, each node has two components, say
vertex and link. The component vertex contains the index of the vertex adjacent
to vertex i.
Consider the directed graphs of Figure 7.1.4. Figure 7.2.1 shows the adjacency list
of the directed graph G2.
Figure 7.2.1 Adjacency list of graph G2 of Figure 7.1.4
Figure 7.2.2 shows the adjacency list of the directed graph G3.
Now that you know how to represent graphs in computer memory, the next
obvious step is to learn the basic operations on a graph. The operations
commonly performed on a graph are as follows:
1. Create the graph. That is, store the graph in computer memory using a
particular graph representation.
2. Clear the graph. This operation makes the graph empty.
3. Determine whether the graph is empty.
4. Traverse the graph.
5. Print the graph.
Graphs as ADT
In this section, we describe the class to implement graphs as an abstract data type
(ADT) and provide the definitions of the functions to implement the operations
on a graph.
The following class defines a graph as an ADT:
A graph is empty if the number of vertices is 0—that is, if gSize is 0. Therefore,
the definition of the function isEmpty is as follows:
The first line of input specifies the number of vertices in the graph. The
first entry in the remaining lines specifies the vertex, and all of the remaining
entries in the line (except the last) specify the vertices that are adjacent to the
vertex. Each line ends with the number –999.
Processing a graph requires the ability to traverse the graph. This section
discusses the graph traversal algorithms.
The two most common graph traversal algorithms are the depth-first
traversal and breadth-first traversal, which are described next. For simplicity, we
assume that when a vertex is visited, its index is output. Moreover, each vertex is
visited only once. We use the bool array visited to keep track of the visited
vertices.
Depth-First Traversal
The depth-first traversal is similar to the preorder traversal of a binary tree. The
general algorithm is as follows:
Consider the graph G3 of Figure 7.1.4. It is shown here again as Figure 7.4.1 for
easy reference.
Figure 7.4.1 Directed graph G3
0 1 2 4 3 5 6 8 10 7 9
For the graph of Figure 7.4.1, the depth-first search starts at the vertex 0. After
visiting all the vertices that can be reached starting at the vertex 0, the depth-first
search starts at the next vertex that is not visited. There is a path from the vertex
0 to every other vertex except the vertices 7 and 9. Therefore, when the depth-
first search starts at the vertex 0, all the vertices except 7 and 9 are visited before
these vertices. After completing the depth-first search that started at the vertex
0, the depth-first search starts at the vertex 7 and then at the vertex 9.
Note that there is no path from the vertex 7 to the vertex 9. Therefore, after
completing the depth-first search that started at the vertex 7, the depth-first
search starts at the vertex 9.
linkedListIterator<int> graphIt;
int w = *graphIt;
The expression *graphIt returns the label of the vertex, adjacent to the vertex v,
to which graphIt points.
0 1 5 2 3 6 4 8 10 7 9
For the graph G3, we start the breadth traversal at vertex 0. After visiting
the vertex 0, we visit the vertices that are directly connected to it and are not
visited, which are 1 and 5.
Next, we visit the vertices that are directly connected to 1 and are not
visited, which are 2 and 3. After this, we visit the vertices that are directly
connected to 5 and are not visited, which is 6. After this, we visit the vertices that
are directly connected to 2 and are not visited, and so on.