07 - APS - Graph
07 - APS - Graph
Graph
Damjan Strnad
2
Graf
●
a graph is a data structure G=(V,E) consisting of a set of
nodes V and a set E of edges (i.e., node pairs) between
nodes
●
example: G=({a,b,c,d,e},{(a,b),(a,c),(b,d),(b,e),(c,d),(d,e)})
a b
c d
●
linked lists and trees are special cases of graphs
a
a b d c b c
d e
3
Graf
●
a graph can be undirected (edges are unordered pairs of
nodes) or directed (first node of the edge is the source and
the second node is the destination)
●
example: G=({a,b,c,d,e},{(a,b),(a,c),(c,a),(d,b),(b,e),(c,d),e,d)})
– the order of nodes in edge
a b
notation is now important
e
●
a complete graph is a graph in c d
Graph
● a path in a graph is every sequence of edges (v1,v2),
(v2,v3), … , (vr-1,vr)
●
a simple path is a path that visits each intermediate node
only once
●
a closed simple path is a cycle
●
a cycle going through all nodes of a graph is a
Hamiltonian cycle
●
an acyclic graph is a graph that contains no cycles
●
a graph is connected, if there is a path between every
pair of nodes
●
a graph is weighted, if edges have assigned weights or
costs; w(u,v) is a weight of edge from u to v
5
Graph representation
●
representation with adjacency lists:
– suitable for sparse graphs for which |E|≪|V|2
– consists of an array Adj which for every graph node u∈V
stores a pointer to a linked list of node‘s neighbors**
– for weighted graphs the edge weight is stored in the nodes
of the linked list
– space complexity for a graph with n nodes is
S(n)=O(|V|+|E|)
A
1 2 1 2 5
2 1 3 4 5
3
3 2 4 5
4 2 3 5
5 4
5 1 2 3 4
6
Graph representation
●
representation with adjacency lists:
– suitable for sparse graphs for which |E|≪|V|2
– consists of an array Adj which for every graph node u∈V
stores a pointer to a linked list of node‘s neighbors**
– for weighted graphs the edge weight is stored in the nodes
of the linked list
– space complexity for a graph with n nodes is
S(n)=O(|V|+|E|)
A
1 2 1 2
2 3
3
3 5
4 2 3
5 4
5 1 2 4
7
Graph representation
●
representation with adjacency lists:
– suitable for sparse graphs for which |E|≪|V|2
– consists of an array Adj which for every graph node u∈V
stores a pointer to a linked list of node‘s neighbors**
– for weighted graphs the edge weight is stored in the nodes
of the linked list
– space complexity for a graph with n nodes is
S(n)=O(|V|+|E|)
3 A
1 2 1 2 3
1
7 2 3 1
1 4 3
3 3 5 3
2 4 2 4 3 2
5 4
8 5 1 1 2 7 4 8
8
Graph representation
●
representation with adjacency matrix:
– suitable for dense graphs for which |E|≈|V|2
– graph nodes are enumerated using indices from 1 to |V|
– adjacency matrix A is of size |V|×|V|, where element aij
determines if there is an edge going from node i to node j:
{
aij = 1 , if (i , j)∈E
0 , otherwise
– space complexity is S(n)=Θ(|V|2)
[ ]
1 2 0 1 0 0 1
1 0 1 1 1
3 A= 0 1 0 1 1
0 1 1 0 1
5 4 1 1 1 1 0
9
Graph representation
●
representation with adjacency matrix:
– suitable for dense graphs for which |E|≈|V|2
– graph nodes are enumerated using indices from 1 to |V|
– adjacency matrix A is of size |V|×|V|, where element aij
determines if there is an edge going from node i to node j:
{
aij = 1 , if (i , j)∈E
0 , otherwise
– space complexity is S(n)=Θ(|V|2)
[ ]
1 2
0 1 0 0 0
0 0 1 0 0
3 A= 0 0 0 0 1
0 1 1 0 0
5 4 1 1 0 1 0
10
Graph representation
●
representation with adjacency matrix:
– for weighted graphs we use:
{
aij = w (i , j), if (i , j)∈E
∞ , otherwise
[ ]
3
1 2 ∞ 3 ∞ ∞ ∞
1
∞ ∞ 1 ∞ ∞
1 7 4 A= ∞ ∞ ∞ ∞ 3
3
3 ∞ 4 2 ∞ ∞
2
5 4 1 7 ∞ 8 ∞
8
11
Graph representation
●
representation with edge list:
– suitable for very sparse graphs and algorithms that iterate over
edges (Prim’s algorithm)
– the list stores edges as pairs (u,v)
– for weighted graphs the list elements are triplets (u,v,w)
– the space complexity is S(n)=O(|E|)
1 2
5 4
1 2 1 5 2 3 2 4 2 5 3 4 3 5 4 5
12
Graph representation
●
representation with edge list:
– suitable for very sparse graphs and algorithms that iterate over
edges (Prim’s algorithm)
– the list stores edges as pairs (u,v)
– for weighted graphs the list elements are triplets (u,v,w)
– the space complexity is S(n)=O(|E|)
3
1 2
1
1 7 4 3
3
2
5 4
8
1 2 3 5 1 1 4 2 4 5 4 8 2 3 1 5 2 7 3 5 3 4 3 2
13
Breadth-first search
●
breadth-first search (BFS) is one of basic algorithms for
searching in graphs:
– we are given a graph G=(V,E) with source node s
– the algorithm systematically follows graph edges and
discovers nodes which are reachable from s
– the first found path from s to arbitrary node v is also the
shortest one if the cost of all edges is the same
– the basic operation is node expansion, where we record
all node‘s successors which have not been recorded before
– the node‘s color shows its status:
●
white nodes have not yet been visited (initial state of all
nodes except source node s)
●
gray nodes have already been visited
●
black nodes have already been expanded (i.e., all
successors have already been visited)
14
Breadth-first search
● for each node v we store its color (color[v]), pointer to
parent (parent[v]) and distance (i.e., the number of edges,
d[v]) from source s
●
expansion sequence is determined by position in a queue, into
which the newly generated (i.e., gray) nodes are added
BREADTH-FIRST-SEARCH(G,s)
for each node u ∈ V – {s} do
color[u] ← WHITE, d[u] ← ∞, parent[u] ← NIL
color[s] ← GRAY, d[s] ← 0, parent[s] ← NIL
Q ← ∅
ENQUEUE(Q,s)
while Q ≠ ∅ do % while queue Q is not empty
u ← DEQUEUE(Q) % remove first node in queue
for each node v ∈ Adj[u] do % check all neighbours of u
if color[v] = WHITE then
color[v] ← GRAY, d[v] ← d[u] + 1, parent[v] ← u
ENQUEUE(Q,v)
color[u] ← BLACK % node u is expanded
15
Q 2
u color[u] parent[u] d[u]
1 w NIL ∞
2 g NIL 0
3 w NIL ∞
4 w NIL ∞
5 w NIL ∞
6 w NIL ∞
7 w NIL ∞
8 w NIL ∞
17
Q 1 3 8
u color[u] parent[u] d[u]
1 g 2 1
2 b NIL 0
3 g 2 1
4 w NIL ∞
5 w NIL ∞
6 w NIL ∞
7 w NIL ∞
8 g 2 1
18
Q 1 3 8
u color[u] parent[u] d[u]
1 g 2 1
2 b NIL 0
3 g 2 1
4 w NIL ∞
5 w NIL ∞
6 w NIL ∞
7 w NIL ∞
8 g 2 1
19
Q 3 8 7
u color[u] parent[u] d[u]
1 b 2 1
2 b NIL 0
3 g 2 1
4 w NIL ∞
5 w NIL ∞
6 w NIL ∞
7 g 1 2
8 g 2 1
20
Q 3 8 7
u color[u] parent[u] d[u]
1 b 2 1
2 b NIL 0
3 g 2 1
4 w NIL ∞
5 w NIL ∞
6 w NIL ∞
7 g 1 2
8 g 2 1
21
Q 8 7 4
u color[u] parent[u] d[u]
1 b 2 1
2 b NIL 0
3 b 2 1
4 g 3 2
5 w NIL ∞
6 w NIL ∞
7 g 1 2
8 g 2 1
22
Q 8 7 4
u color[u] parent[u] d[u]
1 b 2 1
2 b NIL 0
3 b 2 1
4 g 3 2
5 w NIL ∞
6 w NIL ∞
7 g 1 2
8 g 2 1
23
Q 7 4
u color[u] parent[u] d[u]
1 b 2 1
2 b NIL 0
3 b 2 1
4 g 3 2
5 w NIL ∞
6 w NIL ∞
7 g 1 2
8 b 2 1
24
Depth-first search
●
depth-first search (DFS) is similar to breadth-first search
but uses a stack instead of a queue for storing gray nodes
DEPTH-FIRST-SEARCH(G,s)
for each node u ∈ V – {s} do
color[u] ← WHITE, d[u] ← ∞, parent[u] ← NIL
color[s] ← GRAY, d[s] ← 0, parent[s] ← NIL
Q ← ∅
PUSH(S,s)
while S ≠ ∅ do % while stack S is not empty
u ← POP(S) % remove node on top of stack
for each node v ∈ Adj[u] do % check all neighbors of u
if color[v] = WHITE then
color[v] ← GRAY, d[v] ← d[u] + 1, parent[v] ← u
PUSH(S,v)
color[u] ← BLACK % node u is expanded
35