cse 373 graph traversal
play

CSE 373: Graph traversal Michael Lee Friday, Feb 16, 2018 1 Goal: - PowerPoint PPT Presentation

CSE 373: Graph traversal Michael Lee Friday, Feb 16, 2018 1 Goal: How do we traverse graphs? Todays goal: how do we traverse graphs? Idea 1: Just get a list of the vertices and loop over them Problem: What if we want to traverse graphs


  1. Breadth-fjrst search (BFS) queue E . V E , which simplifjes to V So, So we check each edge at most twice For each node, check each edge to see if we should add to Breadth-fjrst traversal, core idea: We visit each node once. 4. Runtime: 3. Use a set to store nodes we don’t want to recheck/revisit 2. Add and remove nodes from queue until it’s empty visit 1. Use something (e.g. a queue) to keep track of every vertex to 4

  2. Breadth-fjrst search (BFS) queue E . V E , which simplifjes to V So, So we check each edge at most twice For each node, check each edge to see if we should add to Breadth-fjrst traversal, core idea: 4. Runtime: 3. Use a set to store nodes we don’t want to recheck/revisit 2. Add and remove nodes from queue until it’s empty visit 1. Use something (e.g. a queue) to keep track of every vertex to 4 ◮ We visit each node once.

  3. Breadth-fjrst search (BFS) queue E . V E , which simplifjes to V So, So we check each edge at most twice 4 Breadth-fjrst traversal, core idea: 4. Runtime: 3. Use a set to store nodes we don’t want to recheck/revisit 2. Add and remove nodes from queue until it’s empty visit 1. Use something (e.g. a queue) to keep track of every vertex to ◮ We visit each node once. ◮ For each node, check each edge to see if we should add to

  4. Breadth-fjrst search (BFS) queue E . V E , which simplifjes to V So, 4 Breadth-fjrst traversal, core idea: 4. Runtime: 3. Use a set to store nodes we don’t want to recheck/revisit 2. Add and remove nodes from queue until it’s empty visit 1. Use something (e.g. a queue) to keep track of every vertex to ◮ We visit each node once. ◮ For each node, check each edge to see if we should add to ◮ So we check each edge at most twice

  5. Breadth-fjrst search (BFS) Breadth-fjrst traversal, core idea: 1. Use something (e.g. a queue) to keep track of every vertex to visit 2. Add and remove nodes from queue until it’s empty 3. Use a set to store nodes we don’t want to recheck/revisit 4. Runtime: queue 4 ◮ We visit each node once. ◮ For each node, check each edge to see if we should add to ◮ So we check each edge at most twice So, O ( | V | + 2 | E | ) , which simplifjes to O ( | V | + | E | ) .

  6. Breadth-fjrst search (BFS) Pseudocode: 5 search(v): visited = empty set queue.enqueue(v) visited.add(v) while (queue is not empty): curr = queue.dequeue() for (w : v.neighbors()): if (w not in visited): queue.enqueue(w) visited.add(curr)

  7. An interesting property... Note: We visited the nodes in “rings” – maintained a gradually growing “frontier” of nodes. a b d c e f g h i j 6

  8. An interesting property... Note: We visited the nodes in “rings” – maintained a gradually growing “frontier” of nodes. a b d c e f g h i j 6

  9. An interesting property... Note: We visited the nodes in “rings” – maintained a gradually growing “frontier” of nodes. a b d c e f g h i j 6

  10. An interesting property... Note: We visited the nodes in “rings” – maintained a gradually growing “frontier” of nodes. a b d c e f g h i j 6

  11. An interesting property... Note: We visited the nodes in “rings” – maintained a gradually growing “frontier” of nodes. a b d c e f g h i j 6

  12. An interesting property... Note: We visited the nodes in “rings” – maintained a gradually growing “frontier” of nodes. a b d c e f g h i j 6

  13. An interesting property... What does this look like for trees? The algorithm traverses the width, or “breadth” of the tree 7

  14. An interesting property... What does this look like for trees? The algorithm traverses the width, or “breadth” of the tree 7

  15. An interesting property... What does this look like for trees? The algorithm traverses the width, or “breadth” of the tree 7

  16. An interesting property... What does this look like for trees? The algorithm traverses the width, or “breadth” of the tree 7

  17. An interesting property... What does this look like for trees? The algorithm traverses the width, or “breadth” of the tree 7

  18. search(v): search(v): visited = empty set visited = empty set stack.push(v) queue.enqueue(v) visited.add(v) visited.add(v) while (stack is not empty): while (queue is not empty): curr = stack.pop() curr = queue.dequeue() visited.add(curr) for (w : v.neighbors()): for (w : v.neighbors()): if (w not in visited): if (w not in visited): queue.enqueue(w) stack.push(w) visited.add(curr) visited.add(v) Depth-fjrst search (DFS) The DFS algorithm: Question: Why a queue? Can we use other data structures? The BFS algorithm: and removes works! For example, what if we try using a stack? Answer: Yes! Any kind of list-like thing that supports appends 8

  19. search(v): search(v): visited = empty set visited = empty set stack.push(v) queue.enqueue(v) visited.add(v) visited.add(v) while (stack is not empty): while (queue is not empty): curr = stack.pop() curr = queue.dequeue() visited.add(curr) for (w : v.neighbors()): for (w : v.neighbors()): if (w not in visited): if (w not in visited): queue.enqueue(w) stack.push(w) visited.add(curr) visited.add(v) Depth-fjrst search (DFS) The DFS algorithm: Question: Why a queue? Can we use other data structures? The BFS algorithm: and removes works! For example, what if we try using a stack? Answer: Yes! Any kind of list-like thing that supports appends 8

  20. search(v): visited = empty set stack.push(v) visited.add(v) while (stack is not empty): curr = stack.pop() visited.add(curr) for (w : v.neighbors()): if (w not in visited): stack.push(w) visited.add(v) Depth-fjrst search (DFS) The DFS algorithm: 8 The BFS algorithm: Question: Why a queue? Can we use other data structures? and removes works! For example, what if we try using a stack? Answer: Yes! Any kind of list-like thing that supports appends search(v): visited = empty set queue.enqueue(v) visited.add(v) while (queue is not empty): curr = queue.dequeue() for (w : v.neighbors()): if (w not in visited): queue.enqueue(w) visited.add(curr)

  21. Depth-fjrst search (DFS) Question: Why a queue? Can we use other data structures? The DFS algorithm: 8 The BFS algorithm: and removes works! For example, what if we try using a stack? Answer: Yes! Any kind of list-like thing that supports appends search(v): search(v): visited = empty set visited = empty set stack.push(v) queue.enqueue(v) visited.add(v) visited.add(v) while (stack is not empty): while (queue is not empty): curr = stack.pop() curr = queue.dequeue() visited.add(curr) for (w : v.neighbors()): for (w : v.neighbors()): if (w not in visited): if (w not in visited): queue.enqueue(w) stack.push(w) visited.add(curr) visited.add(v)

  22. Depth-fjrst search (DFS) example e Visited: a, Stack: a, Current node: j c i h g f d b a 9 search(v): visited = empty set stack.push(v) while (stack is not empty): curr = stack.pop() visited.add(curr) for (w : v.neighbors()): if (w not in visited): stack.push(w)

  23. Depth-fjrst search (DFS) example e Visited: a, Stack: Current node: a j c i h g f d b a 9 search(v): visited = empty set stack.push(v) while (stack is not empty): curr = stack.pop() visited.add(curr) for (w : v.neighbors()): if (w not in visited): stack.push(w)

  24. Depth-fjrst search (DFS) example e Visited: a, b, d, Stack: b, d, Current node: a j c i h g f d b a 9 search(v): visited = empty set stack.push(v) while (stack is not empty): curr = stack.pop() visited.add(curr) for (w : v.neighbors()): if (w not in visited): stack.push(w)

  25. Depth-fjrst search (DFS) example e Visited: a, b, d, Stack: b, Current node: d j c i h g f d b a 9 search(v): visited = empty set stack.push(v) while (stack is not empty): curr = stack.pop() visited.add(curr) for (w : v.neighbors()): if (w not in visited): stack.push(w)

  26. Depth-fjrst search (DFS) example e Visited: a, b, d, e, f, g, Stack: b, e, f, g, Current node: d j c i h g f d b a 9 search(v): visited = empty set stack.push(v) while (stack is not empty): curr = stack.pop() visited.add(curr) for (w : v.neighbors()): if (w not in visited): stack.push(w)

  27. Depth-fjrst search (DFS) example e Visited: a, b, d, e, f, g, Stack: b, e, f, Current node: g j c i h g f d b a 9 search(v): visited = empty set stack.push(v) while (stack is not empty): curr = stack.pop() visited.add(curr) for (w : v.neighbors()): if (w not in visited): stack.push(w)

  28. Depth-fjrst search (DFS) example e Visited: a, b, d, e, f, g, h, i, Stack: b, e, f, h, i, Current node: g j c i h g f d b a 9 search(v): visited = empty set stack.push(v) while (stack is not empty): curr = stack.pop() visited.add(curr) for (w : v.neighbors()): if (w not in visited): stack.push(w)

  29. Depth-fjrst search (DFS) example e Visited: a, b, d, e, f, g, h, i, Stack: b, e, f, h, Current node: i j c i h g f d b a 9 search(v): visited = empty set stack.push(v) while (stack is not empty): curr = stack.pop() visited.add(curr) for (w : v.neighbors()): if (w not in visited): stack.push(w)

  30. Depth-fjrst search (DFS) example e Visited: a, b, d, e, f, g, h, i, Stack: b, e, f, Current node: h j c i h g f d b a 9 search(v): visited = empty set stack.push(v) while (stack is not empty): curr = stack.pop() visited.add(curr) for (w : v.neighbors()): if (w not in visited): stack.push(w)

  31. Depth-fjrst search (DFS) example e Visited: a, b, d, e, f, g, h, i, e, Stack: b, e, Current node: f j c i h g f d b a 9 search(v): visited = empty set stack.push(v) while (stack is not empty): curr = stack.pop() visited.add(curr) for (w : v.neighbors()): if (w not in visited): stack.push(w)

  32. Depth-fjrst search (DFS) example e Visited: a, b, d, e, f, g, h, i, e, Stack: b, e, Current node: e j c i h g f d b a 9 search(v): visited = empty set stack.push(v) while (stack is not empty): curr = stack.pop() visited.add(curr) for (w : v.neighbors()): if (w not in visited): stack.push(w)

  33. Depth-fjrst search (DFS) example e Visited: a, b, d, e, f, g, h, i, e, c, Stack: b, e, c, Current node: e j c i h g f d b a 9 search(v): visited = empty set stack.push(v) while (stack is not empty): curr = stack.pop() visited.add(curr) for (w : v.neighbors()): if (w not in visited): stack.push(w)

  34. Depth-fjrst search (DFS) example e Visited: a, b, d, e, f, g, h, i, e, c, Stack: b, Current node: c j c i h g f d b a 9 search(v): visited = empty set stack.push(v) while (stack is not empty): curr = stack.pop() visited.add(curr) for (w : v.neighbors()): if (w not in visited): stack.push(w)

  35. Depth-fjrst search (DFS) example e Visited: a, b, d, e, f, g, h, i, e, c, Stack: Current node: b j c i h g f d b a 9 search(v): visited = empty set stack.push(v) while (stack is not empty): curr = stack.pop() visited.add(curr) for (w : v.neighbors()): if (w not in visited): stack.push(w)

  36. Depth-fjrst search (DFS) example e Visited: a, b, d, e, f, g, h, i, e, c, Stack: Current node: j c i h g f d b a 9 search(v): visited = empty set stack.push(v) while (stack is not empty): curr = stack.pop() visited.add(curr) for (w : v.neighbors()): if (w not in visited): stack.push(w)

  37. search(v): visited = empty set stack.push(v) visited.add(v) while (stack is not empty): curr = stack.pop() for (w : v.neighbors()): if (w not in visited): stack.push(w) visited.add(curr) Depth-fjrst search (DFS) Depth-fjrst traversal, core idea: Pseudocode: for same reasons as BFS E V 2. Runtime: also everything the same. 1. Instead of using a queue, use a stack. Otherwise, keep 10

  38. search(v): visited = empty set stack.push(v) visited.add(v) while (stack is not empty): curr = stack.pop() for (w : v.neighbors()): if (w not in visited): stack.push(w) visited.add(curr) Depth-fjrst search (DFS) Depth-fjrst traversal, core idea: Pseudocode: everything the same. 1. Instead of using a queue, use a stack. Otherwise, keep 10 2. Runtime: also O ( | V | + | E | ) for same reasons as BFS

  39. Depth-fjrst search (DFS) Pseudocode: Depth-fjrst traversal, core idea: 10 everything the same. 1. Instead of using a queue, use a stack. Otherwise, keep 2. Runtime: also O ( | V | + | E | ) for same reasons as BFS search(v): visited = empty set stack.push(v) visited.add(v) while (stack is not empty): curr = stack.pop() for (w : v.neighbors()): if (w not in visited): stack.push(w) visited.add(curr)

  40. An interesting property... Note: Rather the growing the node in “rings”, we randomly wandered through the graph until we got stuck, then “backtracked”. a b d c e f g h i j 11

  41. An interesting property... Note: Rather the growing the node in “rings”, we randomly wandered through the graph until we got stuck, then “backtracked”. a b d c e f g h i j 11

  42. An interesting property... Note: Rather the growing the node in “rings”, we randomly wandered through the graph until we got stuck, then “backtracked”. a b d c e f g h i j 11

  43. An interesting property... Note: Rather the growing the node in “rings”, we randomly wandered through the graph until we got stuck, then “backtracked”. a b d c e f g h i j 11

  44. An interesting property... Note: Rather the growing the node in “rings”, we randomly wandered through the graph until we got stuck, then “backtracked”. a b d c e f g h i j 11

  45. An interesting property... Note: Rather the growing the node in “rings”, we randomly wandered through the graph until we got stuck, then “backtracked”. a b d c e f g h i j 11

  46. An interesting property... Note: Rather the growing the node in “rings”, we randomly wandered through the graph until we got stuck, then “backtracked”. a b d c e f g h i j 11

  47. An interesting property... Note: Rather the growing the node in “rings”, we randomly wandered through the graph until we got stuck, then “backtracked”. a b d c e f g h i j 11

  48. An interesting property... Note: Rather the growing the node in “rings”, we randomly wandered through the graph until we got stuck, then “backtracked”. a b d c e f g h i j 11

  49. An interesting property... Note: Rather the growing the node in “rings”, we randomly wandered through the graph until we got stuck, then “backtracked”. a b d c e f g h i j 11

  50. An interesting property... Note: Rather the growing the node in “rings”, we randomly wandered through the graph until we got stuck, then “backtracked”. a b d c e f g h i j 11

  51. An interesting property... Note: Rather the growing the node in “rings”, we randomly wandered through the graph until we got stuck, then “backtracked”. a b d c e f g h i j 11

  52. An interesting property... Note: Rather the growing the node in “rings”, we randomly wandered through the graph until we got stuck, then “backtracked”. a b d c e f g h i j 11

  53. An interesting property... Note: Rather the growing the node in “rings”, we randomly wandered through the graph until we got stuck, then “backtracked”. a b d c e f g h i j 11

  54. An interesting property... Note: Rather the growing the node in “rings”, we randomly wandered through the graph until we got stuck, then “backtracked”. a b d c e f g h i j 11

  55. An interesting property... Note: Rather the growing the node in “rings”, we randomly wandered through the graph until we got stuck, then “backtracked”. a b d c e f g h i j 11

  56. An interesting property... Note: Rather the growing the node in “rings”, we randomly wandered through the graph until we got stuck, then “backtracked”. a b d c e f g h i j 11

  57. An interesting property... Note: Rather the growing the node in “rings”, we randomly wandered through the graph until we got stuck, then “backtracked”. a b d c e f g h i j 11

  58. An interesting property... What does this look like for trees? The algorithm traverses to the bottom fjrst: it prioritizes the “depth” of the tree Note: rest of algorithm omitted 12

  59. An interesting property... What does this look like for trees? The algorithm traverses to the bottom fjrst: it prioritizes the “depth” of the tree Note: rest of algorithm omitted 12

  60. An interesting property... What does this look like for trees? The algorithm traverses to the bottom fjrst: it prioritizes the “depth” of the tree Note: rest of algorithm omitted 12

  61. An interesting property... What does this look like for trees? The algorithm traverses to the bottom fjrst: it prioritizes the “depth” of the tree Note: rest of algorithm omitted 12

  62. An interesting property... What does this look like for trees? The algorithm traverses to the bottom fjrst: it prioritizes the “depth” of the tree Note: rest of algorithm omitted 12

  63. An interesting property... What does this look like for trees? The algorithm traverses to the bottom fjrst: it prioritizes the “depth” of the tree Note: rest of algorithm omitted 12

  64. An interesting property... What does this look like for trees? The algorithm traverses to the bottom fjrst: it prioritizes the “depth” of the tree Note: rest of algorithm omitted 12

  65. An interesting property... What does this look like for trees? The algorithm traverses to the bottom fjrst: it prioritizes the “depth” of the tree Note: rest of algorithm omitted 12

  66. An interesting property... What does this look like for trees? The algorithm traverses to the bottom fjrst: it prioritizes the “depth” of the tree Note: rest of algorithm omitted 12

  67. Compare and contrast Question: When do we use BFS vs DFS? Related question: How much memory does BFS and DFS use in the worst case? BFS: V – what if every node is connected to the start? DFS: V – what if the nodes are arranged like a linked list? So, in the worst case, BFS and DFS both have the same worst-case runtime and memory usage. They only difger in what order they visit the nodes. 13

  68. Compare and contrast Question: When do we use BFS vs DFS? Related question: How much memory does BFS and DFS use in the worst case? V – what if every node is connected to the start? V – what if the nodes are arranged like a linked list? So, in the worst case, BFS and DFS both have the same worst-case runtime and memory usage. They only difger in what order they visit the nodes. 13 ◮ BFS: ◮ DFS:

  69. Compare and contrast Question: When do we use BFS vs DFS? Related question: How much memory does BFS and DFS use in the worst case? list? So, in the worst case, BFS and DFS both have the same worst-case runtime and memory usage. They only difger in what order they visit the nodes. 13 ◮ BFS: O ( | V | ) – what if every node is connected to the start? ◮ DFS: O ( | V | ) – what if the nodes are arranged like a linked

  70. Compare and contrast How much memory does BFS and DFS use in the average case? Related question: how much memory do they use when we want to traverse a tree? BFS: “width” of tree num leaves DFS: height For graphs: Use BFS if graph is “narrow”, or if solution is “near” start Use DFS if graph is “wide” In practice, graphs are often large/very wide, so DFS is often a good default choice. (It’s also possible to implement DFS recursively!) 14

  71. Compare and contrast How much memory does BFS and DFS use in the average case? Related question: how much memory do they use when we want to traverse a tree? BFS: “width” of tree num leaves DFS: height For graphs: Use BFS if graph is “narrow”, or if solution is “near” start Use DFS if graph is “wide” In practice, graphs are often large/very wide, so DFS is often a good default choice. (It’s also possible to implement DFS recursively!) 14

  72. Compare and contrast How much memory does BFS and DFS use in the average case? Related question: how much memory do they use when we want to traverse a tree? “width” of tree num leaves height For graphs: Use BFS if graph is “narrow”, or if solution is “near” start Use DFS if graph is “wide” In practice, graphs are often large/very wide, so DFS is often a good default choice. (It’s also possible to implement DFS recursively!) 14 ◮ BFS: ◮ DFS:

  73. Compare and contrast How much memory does BFS and DFS use in the average case? Related question: how much memory do they use when we want to traverse a tree? For graphs: Use BFS if graph is “narrow”, or if solution is “near” start Use DFS if graph is “wide” In practice, graphs are often large/very wide, so DFS is often a good default choice. (It’s also possible to implement DFS recursively!) 14 ◮ BFS: O ( “width” of tree ) = O ( num leaves ) ◮ DFS: O ( height )

  74. Compare and contrast How much memory does BFS and DFS use in the average case? Related question: how much memory do they use when we want to traverse a tree? For graphs: In practice, graphs are often large/very wide, so DFS is often a good default choice. (It’s also possible to implement DFS recursively!) 14 ◮ BFS: O ( “width” of tree ) = O ( num leaves ) ◮ DFS: O ( height ) ◮ Use BFS if graph is “narrow”, or if solution is “near” start ◮ Use DFS if graph is “wide”

  75. Compare and contrast How much memory does BFS and DFS use in the average case? Related question: how much memory do they use when we want to traverse a tree? For graphs: In practice, graphs are often large/very wide, so DFS is often a good default choice. (It’s also possible to implement DFS recursively!) 14 ◮ BFS: O ( “width” of tree ) = O ( num leaves ) ◮ DFS: O ( height ) ◮ Use BFS if graph is “narrow”, or if solution is “near” start ◮ Use DFS if graph is “wide”

Recommend


More recommend