CSE 373: More on graphs; DFS and BFS Two common approaches, with difgerent tradeofgs: 3 Summary What did we learn? Michael Lee , for both directed and undirected graphs. Dense graph , we say the graph is dense . To put it another way, dense graphs have “lots of edges” Sparse graph To put it another way, sparse graphs have “few” edges. 4 How do we represent graphs in code? So, how do we actually represent graphs in code? 5 Either way, it’s still infjnite, for the same reasons given Adjacency matrix Core idea: a b c d a b c d d c b a previously. vertices are independent. have? What if the graph is not simple? is the maximum number of edges it can have, in terms of x ? Some follow-up questions: with y edges. What is the maximum number of vertices it can 2 Infjnite: just keep adding nodes with no edges attached. have, in terms of y ? with y edges. What is the maximum number of vertices it can parallel edges. the graph is not simple? A simple graph is a graph that has no self-loops and no Discuss with your neighbor: Warmup: Warmup 1 Wednesday, Feb 14, 2018 What is the maximum number of edges it can have? What if Warmup: If the graph is simple, the max number of edges is exactly half . can just keep adding more and more self-loops. Note that if 6 ◮ Remind your neighbor: what is a simple graph ? ◮ Suppose we have a simple, directed graph with x nodes. What Each vertex can connect to x − 1 other vertices, so x ( x − 1) . ◮ Now, suppose we have a difgerent simple, undirected graph ◮ Suppose we have a simple, undirected graph with x nodes. ◮ In graphs with no restrictions, number of edges and number of ◮ In simple graphs, if we know | V | is some fjxed value, we also know | E | ∈ O � | V | 2 � of what it would be if the graph were directed. So, x ( x − 1) 2 If the graph is not simple, it’s infjnite: assuming x > 0 , we If | E | ∈ Θ � | V | 2 � x = 0 , there can’t be any edges at all. ◮ Now, suppose we have a difgerent simple, undirected graph If | E | ∈ O ( | V | ) , we sau the graph is sparse . ◮ Assign each node a number from 0 to | V | − 1 ◮ Create a | V | × | V | nested array of booleans or ints ◮ If ( x , y ) ∈ E , then nestedArray[x][y] == true ◮ Adjacency matrix ◮ Adjacency list
Adjacency list d e d c b a Path Path or walk? e c Connected components b a Walk Path or walk? A path is a walk that never visits the same vertex twice. Path More intuitively, a walk is one continous line following the edges. Walk 11 Connected graph What is the worst-case runtime to: a Note: A connected graph has only one connected component. graph) where all vertices are connected to each other. A connected component of a graph is any subgraph (part of a Connected component e d c b Not connected A graph is connected if every vertex is connected to every other Connected or not connected? d c b a Connected Connected or not connected? E.g.: if we pick up the graph and shake it, nothing fmies ofg. vertex via some path. Walks and paths 10 So by default, pick adjacency lists. What is the worst-case runtime to: Is this better for sparse or dense graphs? Dense ones Can we handle self-loops and parallel edges? Self-loops yes, parallel edges, not easily 7 Adjacency list Core idea: a b c comparable worst-case performance 8 Adjacency list We can store edges using either sets or lists. Answer these questions for both. d 12 Can we handle self-loops and parallel edges? Observations: Which do we pick? 9 So which do we pick? How much space do we use? Is this better for sparse or dense graphs? ◮ Get out-edges: O ( | V | ) ◮ Assign each node a number from 0 to | V | − 1 ◮ Get in-edges: O ( | V | ) ◮ Create an array of size | V | ◮ Decide if an edge exists: O (1) ◮ Each element in the array stores its out edges in a list or set ◮ Insert an edge: O (1) ◮ On a higher level: represent as IDictionary<Vertex, ◮ Delete an edge: O (1) Edges> . How much space do we use? O � | V | 2 � ◮ Get out-edges: ◮ Get in-edges: ◮ Most graphs are sparse ◮ Decide if an edge exists: ◮ If we implement adjacency lists using sets, we can get ◮ Insert an edge: ◮ Delete an edge: A walk is a list of vertices v 0 , v 1 , v 2 , . . . , v n where if i is some int where 0 ≤ i < v n , every pair ( v i , v i +1 ) ∈ E is true.
Trees vs graphs g What went wrong? Queue: a, b, d, a, b, e, f, g, Current node: a b d a j i h f A broken traversal e c d b a Is this a graph or tree? 16 Problem: We’re re-visiting nodes we already visited! 15 g Visited: a, b, d, c, e, f, g, h, i, Queue: a, b, d, c, e, f, g, h, i, Current node: a b d c e f g h i j i h f A fjx: Keep track of nodes we’ve already visited in a set! e c d b a Breadth-fjrst search (BFS) example 17 Breadth-fjrst search (BFS) example 18 Tree Rooted tree every other node! Idea: Let’s just fjnd out! Pick a node and see if there’s a path to Question: How can we tell if a graph is connected or not? Detecting if a graph is connected 13 A rooted tree is a tree where we call one special node the “root”. A tree is a connected and acyclic graph. Breadth-fjrst search (BFS) b Yes! (If ‘a’ is the root...) g f d a 14 Breadth-fjrst traversal, core idea: c 4. Keep going until the data structure is empty. a b c d e Pseudocode, version 1: e 1. Pick some node and “mark” it (or save it in a set, etc...) 3. Dequeue some node from the data structure. Go to step 1. f g Both! Is this the same thing? we haven’t visited yet in some data structure, like a queue?) 2. Examine each neighbor and visit each one (note: save the ones search(v): queue.enqueue(v) while (queue is not empty): curr = queue.dequeue() for (w : v.neighbors()): queue.enqueue(w) search(v): visited = empty set queue.enqueue(v) while (queue is not empty): curr = queue.dequeue() for (w : v.neighbors()): queue.enqueue(w) search(v): visited = empty set queue.enqueue(v) visited.add(curr) while (queue is not empty): curr = queue.dequeue() for (w : v.neighbors()): if (w not in visited): queue.enqueue(w) visited.add(curr)
An interesting property... BFS Describe how you would use or modify BFS to solve the following: Other applications of BFS 21 Whatever the largest “horizon size” is. In the worst case, the We visit each vertex once, and each edge once, so Questions: BFS analysis 20 Note: We visited the nodes in “rings” – maintained a gradually Pseudocode 22 19 g growing “frontier” of nodes. a b d c j f e i h search(v): visited = empty set queue.enqueue(v) visited.add(curr) while (queue is not empty): curr = queue.dequeue() for (w : v.neighbors()): if (w not in visited): queue.enqueue(w) visited.add(curr) ◮ What is the worst-case runtime? (Let | V | be the number of vertices, let | E | be the number of edges) ◮ Determine if some graph is also a tree. O ( | V | + | E | ) . ◮ Print out all the elements in a tree level by level. ◮ What is the worst-case amount of memory used? ◮ Find the shortest path from one node to another. horizon will contain | V | − 1 nodes, so O ( | V | ) . Note: O ( | V | + | E | ) is also called “graph linear”.
Recommend
More recommend