Presentation is loading. Please wait.

Presentation is loading. Please wait.

Graphs A New Data Structure

Similar presentations


Presentation on theme: "Graphs A New Data Structure"— Presentation transcript:

1 Graphs A New Data Structure
Data Structures and Algorithms ACA Summer School 2017 Graphs A New Data Structure

2 Shortest path between A and D?
Why Graphs? For example, given a network of cities and roads connecting them, what is the shortest path between two given cities? 7 D 7 B D B 10 10 3 3 A 15 A 15 4 4 C 8 E C 8 E Shortest path between A and D? This is a very natural way to model and think of the given data. Today, we’ll look at this in detail and formalize some notions about this data structure!

3 Graphs A graph G is defined as G = (V, E).
Here, V is a set of vertices and E is a set of edges. Edges may or may not have weights. Weights (optional) Vertices 7 D B 10 3 A 15 4 C E 8 Edges And edge connects two vertices and can be denoted by it’s two endpoints, e.g., (A,C). We have, E ⊆ V × V.

4 Classifications of graphs
Directed Graph Undirected Graph B B A A D D C C V = {A, B, C, D} E = { (A, B), (A,C), (B,D), (C,B), (D, C) } V = {A, B, C, D} E = { (A, B), (A,C), (B,D), (B,C), (C, D) } Note: E is a set. Therefore, in an undirected graph, we write only one of (A,C) and (C, A) since they are the same edge. This is not the case for a directed graph. In general, edge sets cannot tell you whether the graph is directed or undirected. Rather, knowing about the graph tells you how to interpret the edge set.

5 Graph Terminologies Walk:
A walk from x to y is a sequence of vertices <x, v0, v1, …, vk, y> such that (x, v0) ϵ E (vk, y) ϵ E For all i = 0 to k-1, (vi, vi+1) ϵ E Path: A path is a walk <x, v0, v1, …, vk, y> where no vertex gets repeated. Cycle: A cycle is a walk <x, v0, v1, …, vk, y> where no intermediate vertex gets repeated and y=x Examples: <A, B, C, D, B, A, C> is a walk. <A, B, D> is a path. <A, B, D, C, A> is a cycle. <B, C, D, A> is not a walk. Why? B A D C

6 Representations of Graphs
Suppose there are n vertices in the graph. This gives us the vertex set {1, …, n}. Now we need to store the edge set. Here are two ways of doing this. Adjacency Matrix representation We store an n × n size 2D array A (a matrix, essentially). Ai,j = 1 iff there is an edge between i and j in the graph. Size of the representation is O(n2). Adjacency List representation We store a linked list for every vertex. The linked list for vertex i consists of the neighbours of i in the graph. Size of the representation is O(n + m) where m is the number of edges in the graph. Let us look at examples of these now.

7 Representations of Graphs
2 n = 4, m = 5 1 4 3 Adjacency matrix: Adjacency list: 1 2 3 4 1 2 3 X 4

8 Implementations of Graph Data Structures
Adjacency matrix: Use a n x n matrix. Ai, j = weight of edge from node i to node j. Adjacency list: We can use vectors from C++ STL! #include <bits/stdc++.h> using namespace std; // Define the adjacency list as an array of vectors! vector<int> adj[n]; // Function to add an edge between nodes u and v in an undirected graph. void addEdge(vector<int> adj[], int u, int v) { // Add v to adjacency list of u adj[u].push_back(v); // Add u to adjacency list of v adj[v].push_back(u); } There are also other implementations of Adjacency Lists. An array of linked lists is a basic implementation, but it requires careful manipulation of pointers and good knowledge of the workings linked lists and structures.

9 What is the set of vertices reachable from 1?
Graph Traversal What is the set of vertices reachable from 1? 6 1 7 5 9 2 3 4 8 10 11 A vertex y is said to be reachable from vertex x if there exists a path from x to y. Is there a path between 7 and 11? 1 and 8? 1 and 4? No! Yes! Question: Given a vertex x, can we visit all vertices reachable from x? Graph Traversal at x: Visit all vertices reachable from x. How do we perform graph traversal?

10 Breadth First Search – A Graph Traversal Algorithm
Look at neighbours of 1 7 12 6 9 1 5 8 2 13 10 11 3 4 Enqueue 3, 5 Enqueue 2,4 1 3 5 5 2 4 Enqueue 6 Enqueue 8 Enqueue 7 Dequeue 1 and look at neighbours Dequeue 3 and look at neighbours of 3 Dequeue 5 and look at neighbours 6 7 8 4 6 7 2 4 6 Dequeue 6 and look at neighbours Dequeue 4 and look at neighbours Dequeue 2 and look at neighbours 8 7 8 We cannot enqueue any neighbour! Also, no need to update visited array. Dequeue 7 and look at neighbours Imporant: Neighbours of 3 are 1, 2, 4. But we have already visited 1! If we enqueue 1, then we will end up in a loop. So we need the crucial information that we have visited 1, in order to avoid looping! For this, we need to keep another array called visited. Dequeue 8 and look at neighbours Our queue is now empty. We terminate the algorithm here. Check visited array! The only unvisited neighbour is 8! All neighbours visited! The only unvisited neighbour is 6! Mark 6 as visited! 7 is unvisited! Mark 7 as visited! Mark 2, 4 as visited! 3 is visited! We can now check unvisited neighbours of 3. Mark 8 as visited! 1 2 3 4 5 6 7 8 9 10 11 12 13 1 2 3 4 5 6 7 8 9 10 11 12 13 1 2 3 4 5 6 7 8 9 10 11 12 13 1 2 3 4 5 6 7 8 9 10 11 12 13 1 2 3 4 5 6 7 8 9 10 11 12 13

11 Details on Breadth First Search
BFS from 1 visited all vertices reachable from 1. Also, it visited only reachable vertices from 1. Before enqueing, we check if the vertex is visited. And after we enqueue, we mark it visited. So a vertex enters the queue at most once. This is essential to ensure termination. We look at all and only unvisited neighbours while processing a vertex. BFS from 1 visits vertices in increasing order of distance. Distance between x and y is the number of edges in the shortest path from x to y. BFS(G, x) //BFS on graph G, starting at vertex x. Create empty queue Q. Create array visited of length n=|V| and initialize to 0. Enqueue(x,Q); visited[x] = 1; //BFS on graph G, starting at vertex x. while( Q is not empty) { v DeQueue(Q); For each neighbor w of v if(visited[w] == 0) { Enqueue(w,Q); visited[w] = 1; }

12 Breadth First Search - Implementation
// Define the visited array initialized to 0. vector<int> visited(n, 0); deque<int> Q; // Function to perform BFS starting from x void BFS(int x) { // Enqueue x and mark it visited! Q.push_back(x); visited[x]=1; while(!(Q.empty())) //While the queue is not empty // Dequeue operation. int v = Q.pop_front(); num_v = adj[v].size(); for(int i=0; i<num_v; i++) int w = adj[v][i]; if(visited[w] == 0) Q.push_back(w); visited[w] = 1; } Check if w is visited. Enqueue w and mark it visited. After BFS(x) terminates, for all vertices y, visited[y] = 1 iff y is reachable from x.

13 Breadth First Search - Applications
Computing Distances: Given a source vertex x, compute the distance of all vertices from x. Checking for cycles in a graph: Given an undirected graph G, report whether there exists a cycle in the graph or not. (Note: won’t work for directed graphs) Checking for bipartite graph: Given a graph, check whether it is bipartite or not? A graph is said to be bipartite if there is a partition of the vertex set V into two sets V1 and V2 such that if two vertices are adjacent, either both are in V1 or both are in V2. Reachability: Given a graph G and vertices x and y, determine if there exists a path from x to y. For more applications, visit

14 Breadth First Search – Time and Space Complexity
BFS(G, x) //BFS on graph G, starting at vertex x. Create empty queue Q. Create array visited of length n=|V| and initialize to 0. Enqueue(x,Q); visited[x] = 1; //BFS on graph G, starting at vertex x. while( Q is not empty) { v DeQueue(Q); For each neighbor w of v if(visited[w] == 0) { Enqueue(w,Q); visited[w] = 1; } O(n) O(deg(v)) O(1) We keep a queue and a visited array. This takes O(n) space at most. Total space requirement for BFS is therefore O(n). Each node enters queue at most once. Time complexity of BFS traversal is O(n + m).

15 Depth First Search - Another Traversal algorithm
Backtrack! Nowhere to go. 7 12 6 9 1 5 8 2 13 10 11 3 4 4 is unvisited neighbour! Need visited array again! But how do we know? The simple idea is : Keep going as “deep” into the graph as possible. This is done by an unvisited neighbour and visiting it, if it hasn’t been visited. Once all neighbours of the current vertex x have been visited, the control goes to the vertex y that called the procedure on x. Visited array needed to avoid looping! A naturally Recursive procedure due to backtracking. Mark 4 as visited! Mark 5 as visited! Mark 8 as visited! 1 2 3 4 5 6 7 8 9 10 11 12 13 1 2 3 4 5 6 7 8 9 10 11 12 13 1 2 3 4 5 6 7 8 9 10 11 12 13 1 2 3 4 5 6 7 8 9 10 11 12 13

16 Details on Depth First Search
DFS(x) { visited[x] = 1; // Mark x as visited. For each neighbor w of v if(visited[w] == 0) DFS(w); } 7 6 1 5 8 2 3 4 returns returns returns returns DFS(1) DFS(3) DFS(2) DFS(7) DFS(6) calls calls calls calls returns calls Notice a tree-like structure emerging as a result of DFS. This is called the DFS Tree. returns returns DFS(8) calls DFS(4) DFS(5) calls

17 Depth First Search - Applications
Computing Strongly Connected Components: A directed graph is strongly connected if there exists a path from every vertex to every other vertex. Trivial Algo: Perform DFS n times. Efficient Algo: Single DFS. Checking for Biconnected Graph: A graph is biconnected if removal of any vertex does not affect connectivity of the other vertices. Used to test if network is robust to failure of certain nodes. A single DFS traversal algorithm. Topological Ordering: Topological sorting for Directed Acyclic Graph (DAG) is a linear ordering of vertices such that for every directed edge (x, y), vertex x comes before y in the ordering. Plus, almost everything that BFS can do! For more applications, visit In general, DFS is more powerful and more intuitive algorithm, than BFS!

18 DFS and BFS Some Applications.

19 Breadth First Search – A Graph Traversal Algorithm
7 12 6 9 1 5 8 2 13 10 11 3 4 All Vertices at distance 1 All Vertices at distance 0 1 3 5 5 2 4 6 7 8 4 6 7 2 4 6 All Vertices at distance 2 8 7 8 All Vertices at distance 3 Once we process and dequeue all vertices at distance d, the queue contains all and only vertices at distance d+1. 1 2 3 4 5 6 7 8 9 10 11 12 13 1 2 3 4 5 6 7 8 9 10 11 12 13 1 2 3 4 5 6 7 8 9 10 11 12 13 1 2 3 4 5 6 7 8 9 10 11 12 13 1 2 3 4 5 6 7 8 9 10 11 12 13

20 Using BFS to compute distances
BFS from 1 visits vertices in increasing order of distance. BFS(G, x) //BFS on graph G, starting at vertex x. Create empty queue Q. Create array visited of length n=|V| and initialize to 0. Enqueue(x,Q); visited[x] = 1; while( Q is not empty) { v DeQueue(Q); For each neighbor w of v if(visited[w] == 0) Enqueue(w,Q); visited[w] = 1; } Create array distance of length n=|V| and initialize to ∞. distance(x) = 0; Idea: We don’t need visited array because unvisited nodes have distance ∞. So a distance array suffices! if (distance(w) == ∞) distance(w) = distance(v) + 1; Enqueue(w,Q); This is essentially a BFS so time complexity is still O(m + n).

21 Depth First Search - Another Traversal algorithm
7 12 6 9 1 5 8 2 13 10 11 3 4 Keep going as “deep” into the graph as possible. This is done by an unvisited neighbour and visiting it, if it hasn’t been visited. Once all neighbours of the current vertex x have been visited, the control goes to the vertex y that called the procedure on x. Visited array needed to avoid looping! A naturally Recursive procedure due to backtracking. 1 2 3 4 5 6 7 8 9 10 11 12 13 1 2 3 4 5 6 7 8 9 10 11 12 13 1 2 3 4 5 6 7 8 9 10 11 12 13 1 2 3 4 5 6 7 8 9 10 11 12 13

22 Depth First Search - Another Traversal algorithm
Compute property at 7. Want to compute property at 1 7 6 1 5 8 2 3 4 Compute property at 3. Combine properties at 3 and 7 to compute property at 1. This is essentially done using recursion! DFS is naturally recursive and therefore is a suitable choice in this case. Some recursive properties: Height (or depth) of a node in a tree. DFN numbering. Size of subtree. Reachability. …. and many more.


Download ppt "Graphs A New Data Structure"

Similar presentations


Ads by Google