Download presentation
Presentation is loading. Please wait.
1
Depth First Seach: Output Fix
bool findPath (Node* currNode, int destID, list<Edge> path) { if (currNode->id == destID) return true; currNode->visited = true; for each (outEdge of currNode) { Node *toNode = outEdge.toNode; if (!toNode->visited) { list<Edge> newPath = path; newPath.push_back (outEdge); bool found = findPath (toNode, destID, newPath); if (found) return (true); } return (false); Anything Missing? {a,b} {a,b,c} a b c d {} {a,b,c,d} {a} dest source
2
Easy Fix Part 2 dest source
bool findPath (Node* currNode, int destID, list<Edge> path) { if (currNode->id == destID) print out or save the path, then return (true); currNode->visited = true; for each (outEdge of currNode) { Node *toNode = outEdge.toNode; if (!toNode->visited) { list<Edge> newPath = path; newPath.push_back (outEdge); bool found = findPath (toNode, destID, newPath); if (found) return (true); } return (false); dest source
3
Depth First Search (DFS)
Developed depth first search in a graph Need a visited flag Unlike a tree (can go in circles otherwise) Graph is big (>100,000 nodes, N) Complexity of DFS?
4
Complexity Analysis bool findPath (Node* currNode, int destID, list<Edge> path) { if (currNode->id == destID) print out or save the path, then return (true); currNode->visited = true; for each (outEdge of currNode) { Node *toNode = outEdge.toNode; if (!toNode->visited) { list<Edge> newPath = path; newPath.push_back (outEdge); bool found = findPath (toNode, destID, newPath); if (found) return (true); } return (false); At most one findPath call per Node Executes once per outgoing edge Average: about 4
5
Complexity findPath executes at most O(N) times
Constant, O(1), work in each call Except copying path path could have O(N) nodes Total worst-case complexity: O(N2) Average path shorter Average case somewhat better, but hard to analyze
6
Complexity Can we do better? Don’t pass entire path around
One way: each Node stores the edge used to reach it e.g. node.reachingEdge Reconstruct path when you reach the dest By following the previous edges / “bread crumbs” Now work per findPath is O(1) Total complexity is O(N) Good for a graph algorithm!
7
DFS - Demo
8
Path Quality We’re finding a path, not the shortest path
dest source We’re finding a path, not the shortest path Circuitous routes / directions! Low marks! How to fix?
9
Shortest Path Algorithm #2 Depth First Search with Re-Exansion
Path Enumeration Shortest Path Algorithm #2 Depth First Search with Re-Exansion
10
Don’t Stop at First Path Found?
bool findPath (Node* currNode, int destID, float pLen) { pLen = updatePathLength (pLen, currNode); if (currNode->id == destID) if (pLen < bestPathLen) { ...// Update bestPathLen and save best path (globals) } return (true); currNode->visited = true; for each (outEdge of currNode) { Node *toNode = outEdge.toNode; if (!toNode->visited) { bool found = findPath ( toNode, destID); . . . 4 4 3 3 5 1 dest 2 source
11
More Complex Test Case 6 7 2 3 1 dest source 6 4 8 5 This node already marked visited won’t call findPath on it again Blocks us from ever finding best path What can we do?
12
Let a Node be Explored Multiple Times?
bool findPath (Node* currNode, int destID, float pLen) { // Check if we’ve reached the destination // and if this is the best path found so far currNode->visited = true; for each (outEdge of currNode) { Node *toNode = outEdge.toNode; if (!toNode->visited) { bool found = findPath (toNode, destID); if (found) { currNode->visited = false; // Can be explored again return (true); } currNode->visited = false; return (false);
13
Testing DFS with Re-expansion
2 3 6 7 1 dest source 4 8 6 5
14
Testing DFS with Re-expansion
2 3 4 5 1 dest source 4 5 6
15
Testing DFS with Re-expansion
2 3 4 5 1 dest source 2 3 4 6 Not blocked by previously visited nodes! But still avoids infinite loops! Explored all paths to find best one
16
Computational Complexity?
dest source Solve with recurrence Graph above: N-1 nodes T(N-1) to find best path
17
Computational Complexity?
dest source New graph has 1 more node: N nodes T(N) = 2 * T(N-1) (why?) T(N) = 2 * 2 * T(N-2) T(N) = 2 * 2 * 2 * T(N-3) Iterate until we get to T(0) = c T(N) = 2N c O(2N)
18
Algorithm changes big quality and runtime impact!
Fast Enough? N 100,000 Say one call to findPath takes 300 clock 3 GHz 10-7 s DFS with re-expansion (path enumeration) O(2N) 2100,000 10-7 s ~1010,000 years! (Age of the universe ~1010 years) Regular DFS (never explore once visited)? Poor implementation (store / copy whole path) O(N2) 100,0002 10-7 s 1000 s Good implementation O(N) 100,000 10-7 s Less than 1 s! Algorithm changes big quality and runtime impact!
Similar presentations
© 2025 SlidePlayer.com. Inc.
All rights reserved.