Graph Discrete Mathematics and Its Applications Baojian Hua
Graph Discrete Mathematics and Its Applications Baojian Hua bjhua@ustc. edu. cn
What’s a Graph? n Graph: a group of vertices connected by edges
Why Study Graphs? n Interesting & broadly used abstraction n n challenge branch in discrete math n n Ex: the 4 -color problem hundreds of known algorithms n n not only in computer science with more to study numerous applications
Broad Applications Graph Vertices Edges communication software internet social relationship transportation … telephone functions web page people cables calls hyper-links friendship cities … roads …
Graph Terminology 1 2 3 4 5 6 vertex edge: directed vs undirected A sample graph taken from chapter 22 of Introduction to Algorithms.
Graph Terminology 1 2 3 4 5 6 degree: in-degree vs out-degree
Graph ADT n A graph is a tuple (V, E) n n n V is a set of vertices v 1, v 2, … E is a set of vertex tuple <vi, vj> Typical operations: n n graph creation search a vertex (or an edge) traverse all vertexes …
Example G = (V, E) V = {1, 2, 3, 1 2 3 4 5 6 4, 5, 6} E = {(1, 2), (2, 5), (3, 6), (4, 1), (4, 2), (5, 4), (6, 6)}
Representation n Two popular strategies: n array-based (adjacency matrix) n n n Keep an extensible two-dimensional array M internally M[i][j] holds the edge info’ of <vi, vj>, if there exists one linear list-based (adjacency list) n n for every vertex vi, maintain a linear list<vi> stores vi’s outing edges
Adjacency Matrix 0 0 1 2 3 # # # 2 4 5 2 3 4 5 6 5 # 1 3 4 1 # # Note the hash function: hash (n) = n-1
Adjacency List 1 1 ->2 2 2 ->5 3 3 ->5 3 ->6 4 4 ->1 4 ->2 5 5 ->4 6 6 ->6 Notice the pointers!
Graph in C
“graph” ADT in C: Interface // We assume, in this slides, all graphs directed, // and undirected ones are similar and easier. // in file “graph. h” #ifndef GRAPH_H #define GRAPH_H typedef struct graph *graph; graph new. Graph (); void insert. Vertex (graph g, poly data); void insert. Edge (graph g, poly from, poly to); // more to come later … #endif
Graph Implementation #1: Adjacency Matrix // adjacency matrix-based implementation #include “matrix. h” #include “hash. h” #include “graph. h” struct graph { matrix; // remember the index hash; }; 0 0 1 2 3 # # #
Matrix Interface // file “matrix. h” #ifndef MATRIX_H #define MATRIX_H typedef struct matrix *matrix; matrix new. Matrix (); void matrix. Insert (matrix m, int i, int j); int matrix. Extend (matrix m); #endif // Implementation could make use of a two// dimensional extensible array, leave to you.
Adjacency Matrix-based: Graph Creation graph new. Graph () { graph g = malloc (sizeof (*g)); g->matrix = new. Matrix (); // an empty matrix g->hash = new. Hash (); return g; }
Adjacency Matrix-based: Inserting Vertices void insert. Vertex (graph g, poly data) { int i = matrix. Extend (g->matrix); hash. Insert (g->hash, data, i); return; 0 1 2 } 0 0 1 2 3 3 0 # # # 1 1 2 2 3 4 3 # # # 4
Graph Implementation #1: Inserting Edges void insert. Edge (graph g, poly from, poly to) { int f = hash. Lookup (g->hash, from); int t = hash. Lookup (g->hash, to); matrix. Insert (g->matrix, f, t); 0 1 2 3 4 return; 2 3 0 1 } 0 # # 0 1 2 3 # # # 1 2 3 4
Client Code graph g = new. Graph (); insert. Vertex (g, 1); 1 2 3 4 5 6 insert. Vertex (g, 2); … insert. Vertex (g, 6); insert. Edge (g, 1, 2); insert. Edge (g, 2, 5); … insert. Edge (g, 6, 6);
Graph Representation #2: Adjacency List #include “linked. List. h” #include “graph. h” struct graph { linked. List vertices; }; typedef struct vertex *vertex; typedef struct edge *edge; struct vertex { poly data; linked. List edges; }; struct edge { vertex from; vertex to; }
Graph Representation #2: Adjacency List #include “linked. List. h” #include “graph. h” struct graph { linked. List vertices; }; typedef struct vertex *vertex; typedef struct edge *edge; struct vertex { 0 poly data; linked. List edges; 1 }; struct edge { vertex from; 2 vertex to; } 3 0 ->1 0 ->2 0 ->3
Adjacency List-based: Graph Creation // I’ll make use of this convention for colors: // graph, linked. List, data, vertex, edge graph new. Graph () { graph g = malloc (sizeof (*g)); g->vertices = new. Linked. List (); return g; } g vertices /
Adjacency List-based: Creating New Vertex // I’ll make use of this convention for colors: // graph, linked. List, data, vertex, edge vertex new. Vertex (poly data) { vertex v = malloc (sizeof (*v)); v->data = data; v->edges = new. Linked. List (); return v; } v data edges /
Adjacency List-based: Creating New Edge // I’ll make use of this convention for colors: // graph, linked. List, data, vertex, edge new. Edge (vertex from, vertex to) { edge e = malloc (sizeof (*e)); e->from = from; e->to = to; return e; } e from to to
Adjacency List-based: Inserting New Vertex void insert. Vertex (graph g, poly data) { vertex v = new. Vertex (data); linked. List. Insert. Tail (g->vertices, v); return; 0 ->1 0 ->2 0 } 1 2 3 4 0 ->3
Adjacency List-based: Inserting New Vertex void insert. Vertex (graph g, poly data) { vertex v = new. Vertex (data); linked. List. Insert. Tail (g->vertices, v); return; 0 ->1 0 ->2 0 } 1 2 3 4 0 ->3
Adjacency List-based: Inserting New Vertex void insert. Vertex (graph g, poly data) { vertex v = new. Vertex (data); linked. List. Insert. Tail (g->vertices, v); return; 0 ->1 0 ->2 0 } 1 2 3 4 0 ->3
Adjacency List-based: Inserting New Edge void insert. Edge (graph g, poly from, poly to) { vertex vf = lookup. Vertex (g, from); vertex vt = lookup. Vertex (g, to); edge e = new. Edge (vf, vt); 0 ->1 0 ->2 0 ->3 0 (vf->edges, linked. List. Insert. Tail e); return; 1 } 2 // insert 0 ->4 3 4
Adjacency List-based: Inserting New Edge void insert. Edge (graph g, poly from, poly to) { vertex vf = lookup. Vertex (g, from); vertex vt = lookup. Vertex (g, to); edge e = new. Edge (vf, vt); 0 ->1 0 ->2 0 ->3 0 (vf->edges, linked. List. Insert. Tail e); return; 1 } 2 3 4
Adjacency List-based: Inserting New Edge void insert. Edge (graph g, poly from, poly to) { vertex vf = lookup. Vertex (g, from); vertex vt = lookup. Vertex (g, to); edge e = new. Edge (vf, vt); 0 ->1 0 ->2 0 ->3 0 (vf->edges, linked. List. Insert. Tail e); return; 1 } 2 3 4
Adjacency List-based: Inserting New Edge void insert. Edge (graph g, poly from, poly to) { vertex vf = lookup. Vertex (g, from); vertex vt = lookup. Vertex (g, to); edge e = new. Edge (vf, vt); 0 ->1 0 ->2 0 ->3 0 (vf->edges, linked. List. Insert. Tail e); return; 1 } 2 3 4 0 ->4
Adjacency List-based: Inserting New Edge void insert. Edge (graph g, poly from, poly to) { vertex vf = lookup. Vertex (g, from); vertex vt = lookup. Vertex (g, to); edge e = new. Edge (vf, vt); 0 ->1 0 ->2 0 ->3 0 (vf->edges, linked. List. Insert. Tail e); return; 1 } 2 3 4 0 ->4
Example 1 2 3 4 5 6
Client Code for This Example: Step #1: Cook Data str gname = new. Str (“test”); graph = new. Graph (gname); nat nat nat n 1 n 2 n 3 n 4 n 5 n 6 = = = new. Nat (1); (2); (3); (4); (5); (6); 1 2 3 4 5 6
Client Code Continued: Step #2: Insert Vertices graph. Insert. Vertex (graph, (graph, n 1); n 2); n 3); n 4); n 5); n 6); 1 2 3 4 5 6
Client Code Continued: Step #3: Insert Edges graph. Insert. Edge graph. Insert. Edge (graph, (graph, n 1, n 2, n 3, n 4, n 5, n 6, n 2); n 5); n 6); n 1); n 2); n 4); n 6); 1 2 3 4 5 6 // Done! : -)
Example In Picture: An Empty Graph g // I’ll make use of this convention for colors: // graph, linked. List, data, vertex, edge next data
Example In Picture: After Inserting all Vertices g // I’ll make use of this convention for colors: // graph, linked. List, data, vertex, edge next data 1 / 2 3 5 4 6 data next / / /
Example In Picture: After Inserting all Edges (Part) g // I’ll make use of this convention for colors: // graph, linked. List, data, vertex, edge next data 1 / 2 3 5 4 6 data next from to / /
Graph Traversal
Searching n n The systematic way to traverse all vertex in a graph Two general methods: n breath first searching (BFS) n n depth first searching (DFS) n n start from one vertex, first visit all the adjacency vertices eager method These slides assume the adjacency list representation
“graph” ADT in C: Interface // in file “graph. h” #ifndef GRAPH_H #define GRAPH_H typedef struct graph *graph; typedef void (*ty. Visit)(poly); graph new. Graph (); void insert. Vertex (graph g, poly data); void insert. Edge (graph g, poly from, poly to); void dfs (graph g, poly start, ty. Visit visit); void bfs (graph g, poly start, ty. Visit visit); // we’d see more later … #endif
Sample Graph 1 2 3 4 5 6
Sample Graph BFS bfs (g, 1, nat. Output); 1 2 3 4 5 6
Sample Graph BFS bfs (g, 1, nat. Output); print 1; 1 2 3 4 5 6
Sample Graph BFS bfs (g, 1, nat. Output); print 1; 1 2 3 4 5 6 // a choice print 2;
Sample Graph BFS bfs (g, 1, nat. Output); print 1; 1 2 3 4 5 6 // a choice print 2; print 4;
Sample Graph BFS bfs (g, 1, nat. Output); print 1; 1 2 3 4 5 6 // a choice print 2; print 4; print 5;
Sample Graph BFS bfs (g, 1, nat. Output); print 1; 1 2 3 4 5 6 // a choice print 2; print 4; print 5; // a choice print 3;
Sample Graph BFS bfs (g, 1, nat. Output); print 1; 1 2 3 4 5 6 // a choice print 2; print 4; print 5; // a choice print 3; print 6;
BFS Algorithm bfs (vertex start, ty. Visit visit) { queue q = new. Queue (); en. Queue (q, start); while (q not empty) { vertex current = de. Queue (q); visit (current); for (each adjacent vertex u of “current”){ if (not visited u) en. Queue (q, u); } } }
BFS Algorithm void bfs. Main (graph g, poly start, ty. Visit visit) { vertex start. V = search. Vertex (g, start); bfs (start. V, visit); for (each vertex u in graph g) if (not visited u) bfs (q, u); }
Sample Graph BFS bfs (g, 1, nat. Output); 1 2 3 4 5 6 Queue: 1
Sample Graph BFS bfs (g, 1, nat. Output); print 1; 1 2 3 4 5 6 Queue: 1 Queue: 2, 4
Sample Graph BFS bfs (g, 1, nat. Output); print 1; 1 2 3 4 5 6 // a choice print 2; Queue: 1 Queue: 2, 4 Queue: 4, 5
Sample Graph BFS bfs (g, 1, nat. Output); print 1; 1 2 3 4 5 6 // a choice print 2; print 4; Queue: 1 Queue: 2, 4 4, 5 5
Sample Graph BFS bfs (g, 1, nat. Output); print 1; 1 2 3 4 5 6 // a choice print 2; print 4; print 5; Queue: 1 Queue: 2, 4 4, 5 5 Queue: 3
Sample Graph BFS bfs (g, 1, nat. Output); print 1; 1 2 3 4 5 6 // a choice print 2; print 4; print 5; Queue: 1 // a choice Queue: print 3; Queue: 2, 4 4, 5 5 Queue: 3 Queue: 6
Sample Graph BFS bfs (g, 1, nat. Output); print 1; 1 2 3 4 5 6 // a choice print 2; print 4; print 5; Queue: 1 // a choice Queue: print 3; Queue: print 6; Queue: 2, 4 4, 5 5 Queue: 3 Queue: 6
Moral n n n BFS is very much like the level-order traversal on trees Maintain internally a queue to control the visit order Obtain a BFS forest when finished
Sample Graph DFS dfs (g, 1, nat. Output); 1 2 3 4 5 6
Sample Graph DFS dfs (g, 1, nat. Output); print 1; 1 2 3 4 5 6
Sample Graph DFS dfs (g, 1, nat. Output); print 1; 1 2 3 4 5 6 // a choice print 2;
Sample Graph DFS dfs (g, 1, nat. Output); print 1; 1 2 3 4 5 6 // a choice print 2; print 5;
Sample Graph DFS dfs (g, 1, nat. Output); print 1; 1 2 3 4 5 6 // a choice print 2; print 5; print 4;
Sample Graph DFS dfs (g, 1, nat. Output); print 1; 1 2 3 4 5 6 // a choice print 2; print 5; print 4; // a choice print 3;
Sample Graph DFS dfs (g, 1, nat. Output); print 1; 1 2 3 4 5 6 // a choice print 2; print 5; print 4; // a choice print 3; print 6;
DFS Algorithm dfs (vertex start, ty. Visit visit) { visit (start); for (each adjacent vertex u of “start”) if (not visited u) dfs (u, visit); }
DFS Algorithm void dfs. Main (graph g, poly start, ty. Visit visit) { vertex start. V = search. Vertex (g, start); dfs (start. V, visit); for (each vertex u in graph g) if (not visited u) dfs (u, visit); }
Sample Graph DFS dfs (g, 1, nat. Output); print 1; 1 2 3 4 5 6 dfs(1)
Sample Graph DFS dfs (g, 1, nat. Output); print 1; 1 2 3 4 5 6 // a choice print 2; dfs(1) => dfs(2)
Sample Graph DFS dfs (g, 1, nat. Output); print 1; 1 2 3 4 5 6 // a choice print 2; print 5; dfs(1) => dfs(2) => dfs(5)
Sample Graph DFS dfs (g, 1, nat. Output); print 1; 1 2 3 4 5 6 // a choice print 2; print 5; print 4; dfs(1) => dfs(2) => dfs(5) => dfs(4)
Sample Graph DFS dfs (g, 1, nat. Output); print 1; 1 2 3 4 5 6 // a choice print 2; print 5; print 4; dfs(1) => dfs(2) => dfs(5) => dfs(4) => dfs(2)? ? ?
Sample Graph DFS dfs (g, 1, nat. Output); print 1; 1 2 3 4 5 6 // a choice print 2; print 5; print 4; dfs(1) => dfs(2) => dfs(5)
Sample Graph DFS dfs (g, 1, nat. Output); print 1; 1 2 3 4 5 6 // a choice print 2; print 5; print 4; dfs(1) => dfs(2)
Sample Graph DFS dfs (g, 1, nat. Output); print 1; 1 2 3 4 5 6 // a choice print 2; print 5; print 4; dfs(1)
Sample Graph DFS dfs (g, 1, nat. Output); print 1; 1 2 3 4 5 6 // a choice print 2; print 5; print 4; dfs(1) =>dfs(4)? ? ?
Sample Graph DFS dfs (g, 1, nat. Output); print 1; 1 2 3 4 5 6 // a choice print 2; print 5; print 4; dfs(1)
Sample Graph DFS dfs (g, 1, nat. Output); print 1; 1 2 3 4 5 6 // a choice print 2; print 5; print 4; empty!
Sample Graph DFS dfs (g, 1, nat. Output); print 1; 1 2 3 4 5 6 // a choice print 2; print 5; print 4; // a choice print 3; dfs(3)
Sample Graph DFS dfs (g, 1, nat. Output); print 1; 1 2 3 4 5 6 // a choice print 2; print 5; print 4; // a choice print 3; print 6; dfs(3) =>dfs(6)
Sample Graph DFS dfs (g, 1, nat. Output); print 1; 1 2 3 4 5 6 // a choice print 2; print 5; print 4; // a choice print 3; print 6; dfs(3) =>dfs(6)? ? ?
Sample Graph DFS dfs (g, 1, nat. Output); print 1; 1 2 3 4 5 6 // a choice print 2; print 5; print 4; // a choice print 3; print 6; dfs(3) =>dfs(6)
Sample Graph DFS dfs (g, 1, nat. Output); print 1; 1 2 3 4 5 6 // a choice print 2; print 5; print 4; // a choice print 3; print 6; dfs(3)
Sample Graph DFS dfs (g, 1, nat. Output); print 1; 1 2 3 4 5 6 // a choice print 2; print 5; print 4; // a choice print 3; print 6; dfs(3) =>dfs(5)? ? ?
Sample Graph DFS dfs (g, 1, nat. Output); print 1; 1 2 3 4 5 6 // a choice print 2; print 5; print 4; // a choice print 3; print 6; dfs(3)
Sample Graph DFS dfs (g, 1, nat. Output); print 1; 1 2 3 4 5 6 // a choice print 2; print 5; print 4; // a choice print 3; print 6; empty!
Moral n n DFS is very much like the pre-order traversal on trees Maintain internally a stack to control the visit order n n for recursion function, machine maintain an implicit stack Obtain a DFS forest when finished
Edge Classification n Once we obtain the DFS (or BFS) spanning trees (forests), the graph edges could be classified according to the trees: n n tree edges: edges in the trees forward edges: ancestors to descants back edges: descants to ancestors cross edges: others
Edge Classification Example • tree edges: 1 ->2, 2 ->5, 5 ->4, 3 ->6 1 2 3 4 5 6 • forward edges: 1 ->4 • back edges: 4 ->2, 6 ->6 • cross edges: 3 ->5
- Slides: 91