You are on page 1of 22

Elementary Graph Algorithms

Chapter 22

Graph Basics
A graph is a set of vertices (points) and edges (connections between points) General notation: G = (V, E) A graph is directed if the edges are one-directional (contain an arrowhead) A graph is undirected if the edges indicate no direction (do not contain an arrowhead)

Representations of Graphs
Adjacency list
Array of lists, one for each vertex

Adjacency matrix
Matrix or two-dimensional grid, rows and columns represent vertices

Adjacency List
Array of lists, one for each vertex For each vertex u, the list for u contains all other vertices v such that there is an edge (u, v), i.e., all vertices adjacent to u in G
Undirected graph: Directed graph:

Size of Adjacency Lists


For a directed graph, number of elements among all adjacency lists is |E| For an undirected graph, number of elements among all adjacency lists is 2|E| Amount of memory required is (V+E)

Adjacency Matrix
Matrix of size |V|x|V| Rows and columns represent vertices For row i and column j, matrix entry (i, j) is 1 if (i, j) is an edge, and 0 otherwise
Undirected graph: Directed graph:

Size of Adjacency Matrices


Requires (V2) memory, independent of the number of edges For an undirected graph, there is symmetry along the main diagonal, thus can store only the entries on and above the diagonal

Adjacency List vs. Adjacency Matrix


Adjacency list
More compact uses less space Good for representing sparse graphs (few edges) Not easy to tell if an edge exists between two given vertices More commonly used

Adjacency matrix
Uses more space Good for representing dense graphs (many edges) Can easily tell if an edge exists between two given vertices Simpler, so good for small graphs

Breadth-First Search
Given a graph G and a source vertex s, find every vertex that is reachable from s Computes distance (smallest number of edges) from s to each reachable vertex Explores all vertices at distance k from s before exploring at distance k+1 (i.e., spans the width) Produces breadth-first tree with root s containing all reachable vertices Simple path from s to v in this tree corresponds to a shortest path from s to v in G (i.e., path containing the smallest number of edges)

BFS Algorithm
BFS(G, s) 1 for each vertex u in G.V {s} 2 u.color = WHITE // mark as unseen 3 u.d = // distance from s 4 u. = NIL // predecessor 5 s.color = GRAY // mark as seen 6 s.d = 0 7 s. = NIL 8 Q = // FIFO queue 9 ENQUEUE(Q, s) // insert source vertex 10 while Q 11 u = DEQUEUE(Q) 12 for each v in G.Adj*u+ // for each of us neighbors 13 if v.color == WHITE // if unseen 14 v.color = GRAY // mark as seen 15 v.d = u.d + 1 16 v. = u 17 ENQUEUE(Q, v) 18 u.color = BLACK // mark as done, all neighbors have been examined

BFS Examples

Source vertex: s

Source vertex: 3

Run time of BFS


Each enqueuing and dequeuing: O(1) time Total time for queue operations: O(V) Scanning adjacency lists: O(E) Initialization: O(V) Total running time: O(V+E) Linear in the size of the adjacency list representation of G

Printing the Shortest Path


PRINT-PATH(G, s, v) 1 if v == s 2 print s 3 else if v. == NIL 4 print no path from s to v exists 5 else PRINT-PATH(G, s, v.) 6 print v

Runs in time linear in the number of vertices in the path

Depth-First Search
Search deeper whenever possible Explore edges out of the most recently seen vertex v that still has unexplored edges leaving it After exploring all of vs edges, backtrack to explore edges leaving the vertex from which v was first seen Continue until all vertices have been seen Can search from multiple sources Produces a depth-first forest with possibly multiple depth-first trees

DFS Algorithm
DFS(G) 1 for each vertex u in G.V 2 u.color = WHITE 3 u. = NIL 4 time = 0 5 for each vertex u in G.V 6 if u.color == WHITE // if unseen 7 DFS-VISIT(G, u) // explore paths out of u

DFS-VISIT(G, u) 1 time = time + 1 // white vertex u has just been discovered 2 u.d = time // discovery time of u 3 u.color = GRAY // mark as seen 4 for each v in G.Adj[u] // explore edge (u, v) 5 if v.color == WHITE // if unseen 6 v. = u 7 DFS-VISIT(G, v) // explore paths out of v (i.e., go deeper) 8 u.color = BLACK // u is finished 9 time = time + 1 10 u.f = time // finish time of u

DFS Examples

Source vertex: 1

Source vertex: s

Run time of DFS


Loops in DFS: (V) DFS-VISIT called for each vertex in V Adjacency list scans in DFS-VISIT: (E) Total run time: (V+E)

Topological Sort
Linear ordering of all vertices such that for each edge (u, v), u appears before v in the ordering Ordering of vertices along a horizontal line so that all directed edges go from left to right Indicates precedences among events Graph must be directed and acyclic (DAG)

Topological Sort Algorithm


DFS(G) 1 for each vertex u in G.V 2 u.color = WHITE 3 u. = NIL 4 time = 0 5 for each vertex u in G.V 6 if u.color == WHITE // if unseen 7 DFS-VISIT(G, u) // explore paths out of u

DFS-VISIT(G, u) 1 time = time + 1 // white vertex u has just been discovered 2 u.d = time // discovery time of u 3 u.color = GRAY // mark as seen 4 for each v in G.Adj[u] // explore edge (u, v) 5 if v.color == WHITE // if unseen 6 v. = u 7 DFS-VISIT(G, v) // explore paths out of v (i.e., go deeper) 8 u.color = BLACK // u is finished 9 time = time + 1 10 u.f = time // finish time of u 11 toposort-list.prepend(u)

Example
Getting dressed in the morning Must put on certain garments before others (e.g., socks before shoes) Others can be put on in any order (e.g., socks and pants) Directed edge (u, v) indicates garment u must be put on before garment v Topological sort gives order for getting dressed

Example

Topologically sorted vertices appear in reverse order of their finish times

Another Example
1 2 3

10

You might also like