1 / 36

Dijkstra's Algorithm

Dijkstra's Algorithm. Using a Weighted Graph. Objective. You will be able to: Describe an ADT for a weighted graph. Implement an ADT for a weighted graph. Implement Dijkstra's algorithm for finding the minimum cost path between two nodes in a weighted graph. Edsger Dijkstra.

ova
Download Presentation

Dijkstra's Algorithm

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Dijkstra's Algorithm Using a Weighted Graph

  2. Objective • You will be able to: • Describe an ADT for a weighted graph. • Implement an ADT for a weighted graph. • Implement Dijkstra's algorithm for finding the minimum cost path between two nodes in a weighted graph.

  3. Edsger Dijkstra • 1959 Shortest Path Algorithm (Graph Theory) • 1968 The "THE" Operating System • 1968 "Go To Consider Harmful" (Niklaus Wirth, Editor) • 1972 ACM Turing Award • 1984 - 2002 University of Texas • http://en.wikipedia.org/wiki/Edsger_W._Dijkstra 1930 - 2002

  4. A Weighted Graph ADT • A Set of Nodes (Vertices) • Numbered 1 .. N • A Set of bidirectional Edges (pairs of Nodes) • A nonnegative weight for each edge. • "Cost" or "Distance"

  5. Problem: Find Best Path • Find a Path from a specified starting node to a specified destination node such that the sum of the weights of the edges is minimized.

  6. A Weighted Graph ADT • Create a new project. • Weighted_Graph_Demo • Add main.cpp • Start with "Hello, World!"

  7. main.cpp #include <iostream> using namespace std; int main (void) { cout << "This is the Weighted Graph Demo\n"; cin.get(); return 0; }

  8. Weighted_Graph.h • Add new item: • Weighted_Graph.h • This will be our weighted graph ADT template. • Will represent the graph with an adjacency matrix. • distance[i][j] is distance from node i to node j • weight of the edge between node i and node j • 0 if no edge between i and j

  9. The Weighted Graph ADT • Nodes will be an arbitrary type. • Template parameter T • Must define operators =, ==, and << • Externally nodes are identified by objects of class T. • Example: Strings • Internally nodes are identified by integer Node IDs, 1 ... N

  10. Weighted_Graph.h #pragma once #ifndef MAX_NODES #define MAX_NODES 100 #endif using namespace std; template <typename T> class Weighted_Graph { private: int number_of_nodes; // The Node ID 0 is not used. The first real node has ID 1 T nodes[MAX_NODES+1]; int distance[MAX_NODES+1][MAX_NODES+1]; public: Weighted_Graph(); void Add_Node(const T& node); void Add_Edge(const T& Node_1, const T& Node_2, int dist); void Display() const; };

  11. Implementation • Constructor template <typename T> Weighted_Graph<T>::Weighted_Graph() : number_of_nodes(0) {};

  12. Add_Node template <typename T> void Weighted_Graph<T>::Add_Node (const T& node) { assert(number_of_nodes < MAX_NODES); int n = ++number_of_nodes; nodes[n] = node; for (int i = 1; i < n; ++i) { distance[i][n] = 0; distance[n][i] = 0; } }

  13. Add_Edge template <typename T> void Weighted_Graph<T>::Add_Edge(const T& Node_1, const T& Node_2, int dist) { int Node_ID_1 = Get_Node_ID(Node_1); int Node_ID_2 = Get_Node_ID(Node_2); assert ((Node_ID_1 > 0) && (Node_ID_2 > 0)); distance[Node_ID_1][Node_ID_2] = dist; distance[Node_ID_2][Node_ID_1] = dist; } Add at top: #include <cassert>

  14. Get_Node_ID template <typename T> int Weighted_Graph<T>::Get_Node_ID(const T& node) const { for (int i = 1; i <= number_of_nodes; ++i) { if (nodes[i] == node) { return i; } } cout << "Node " << node << " not found\n"; return -1; }

  15. Get_Node_ID Also add to class definition. private: int Get_Node_ID(const T& Node) const;

  16. Display template <typename T> void Weighted_Graph<T>::Display() const { cout << endl; cout << setw(10) << " "; for (int i = 1; i <= number_of_nodes; ++i) { cout << setw(10) << nodes[i] << " "; } cout << endl; for (int i = 1; i <= number_of_nodes; ++i) { cout << setw(10) << nodes[i]; for (int j = 1; j <= number_of_nodes; ++j) { cout << setw(10) << distance[i][j] << " "; } cout << endl; } cout << endl; }

  17. Weighted_Graph.h • Add at top: #include <iostream> #include <iomanip>

  18. Washington Chicago Austin Denver Atlanta Dallas Houston Example: Airline connections 1000 900 600 1400 780 1300 200 800 160

  19. main.cpp #include <iostream> #include <string> #include "Weighted_Graph.h" using namespace std; Weighted_Graph<string> connections;

  20. Add to main() connections.Add_Node(string("Atlanta")); connections.Add_Node(string("Austin")); connections.Add_Node(string("Chicago")); connections.Add_Node(string("Dallas")); connections.Add_Node(string("Denver")); connections.Add_Node(string("Houston")); connections.Add_Node(string("Washington")); connections.Add_Edge(string("Atlanta"), string("Denver"), 1400); connections.Add_Edge(string("Atlanta"), string("Houston"), 800); connections.Add_Edge(string("Atlanta"), string("Washington"), 600); connections.Add_Edge(string("Austin"), string("Dallas"), 200); connections.Add_Edge(string("Austin"), string("Houston"), 160); connections.Add_Edge(string("Chicago"), string("Dallas"), 900); connections.Add_Edge(string("Chicago"), string("Denver"), 1000); connections.Add_Edge(string("Dallas"), string("Denver"), 780); connections.Add_Edge(string("Dallas"), string("Washington"), 1300); connections.Display();

  21. Program Running

  22. Dijkstra's Algorithm • Given a starting node and a destination node • Push outward from the starting node • Keeping track of the shortest total distance seen so far to each node and the predecessor to that node on the shortest path seen so far. • Initially if the node is adjacent to the start • Shortest total distance seen so far is the weight of the link • Predecessor on best path is the start • If node is not adjacent • Shortest distance seen so far is infinity (INT_MAX)

  23. Dijkstra's Algorithm • On each step of the iteration, the shortest total distance to one more node will be determined • And its predecessor on the best path to it from the starting node. • Keep track of which nodes we know the shortest distance to. • Boolean array indexed by Node ID

  24. Dijkstra's Algorithm • At each step of the iteration: • Determine a node with smallest "Best total distance seen so far" among the nodes for which the best total distance has not yet been determined. • Call it node N. • The best distance so far for node N is the actual best distance. • The predecessor for which that distance was determined is is predecessor on the best path. • The best path to that node is now known.

  25. Dijkstra's Algorithm • Update best distances • For each node, i, for which the best path has not yet been determined -- • Check if the node N provides a better path than the best seen so far. • Is Total Distance[N] + Distance(N,i) less than Best Total Distance Seen So for for Node i? • If so, make that the new best total distance so far and make node N the predecessor.

  26. Dijkstra's Algorithm • Continue the iteration until the actual shortest total distance for the destination has been determined. • We then know the shortest path length from Start to Destination and the best path. • Follow predecessors from Destination back to Start.

  27. Best_Path • Add to Weighted_Graph class defintion: #include <deque> public: ... deque<T> Best_Path(const T& Start, const T& Dest) const; • Will return the best path from Start to Dest to the caller in the form of an STL deque. • doubly ended queue

  28. Best_Path // Dijkstra's Algorithm template <typename T> deque<T> Weighted_Graph<T>::Best_Path(const T& Start, const T& Dest) const { deque<T> best_path; int best_total_distance_so_far[MAX_NODES+1]; int predecessor[MAX_NODES+1]; bool best_total_distance_is_known[MAX_NODES+1]; if (Dest == Start) { cout << "Dest = Start in call to Best_Path\n"; return best_path; // Return empty deque. } int Start_ID = Get_Node_ID(Start); int Dest_ID = Get_Node_ID(Dest); if ((Start_ID <= 0) || (Dest_ID <= 0)) { cout << "Invalid start or destination\n"; return best_path; // empty deque }

  29. Best_Path for (int i = 1; i <= MAX_NODES; ++i) { if (distance[Start_ID][i] > 0) { best_total_distance_so_far[i] = distance[Start_ID][i]; predecessor[i] = Start_ID; } else { best_total_distance_so_far[i] = INT_MAX; predecessor[i] = -1; } best_total_distance_is_known[i] = false; } best_total_distance_so_far[Start_ID] = 0; best_total_distance_is_known[Start_ID] = true;

  30. Best_Path (continued) while (!best_total_distance_is_known[Dest_ID]) { // Determine the node with least distance among // all nodes whose best distance is not yet known. int min_best_dist = INT_MAX; int best_node_id = -1; for (int i = 1; i <= number_of_nodes; ++i) { if (best_total_distance_is_known[i]) { continue; } if (best_total_distance_so_far[i] < min_best_dist) { min_best_dist = best_total_distance_so_far[i]; best_node_id = i; } }

  31. Best_Path (continued) if (best_node_id == -1) { // Destination is unreachable. cout << Dest << " is unreachable from " << Start << endl; return best_path; // empty deque } // Best total distance so farfor this node is the actual // best total distance . int n = best_node_id; best_total_distance_is_known[n] = true;

  32. Best_Path (continued) // Check if this node provdes a better route to the destination // for other nodes whose best distance is not yet known. for (int i = 1; i <= number_of_nodes; ++i) { if (best_total_distance_is_known[i]) { continue; } if (distance[n][i] <= 0) { continue; // No connection from node n to node i } if ((best_total_distance_so_far[n] + distance[n][i]) < best_total_distance_so_far[i]) { // It does. best_total_distance_so_far[i] = best_total_distance_so_far[n] + distance[n][i]; predecessor[i] = n; } } }

  33. Best_Path (continued) // At this point we know predecessor of each node on the // best path from Start to Dest best_path.push_front(Dest); int next_node_id = Dest_ID; while (next_node_id != Start_ID) { next_node_id = predecessor[next_node_id]; best_path.push_front(nodes[next_node_id]); } return best_path; }

  34. main.cpp void Show_Best_Path(string Start, string Dest) { deque<string> best_path = connections.Best_Path(Start, Dest); if (best_path.size() == 0) { cout << "No path found\n"; } else { cout << "Best path:\n"; while (best_path.size() > 0) { string next = best_path.front(); best_path.pop_front(); cout << next << endl; } } cout << endl; }

  35. main.cpp connections.Display(); cout << endl; while (true) { string start; string dest; cout << "Start: "; getline(cin, start); cout << "Destination: "; getline(cin, dest); Show_Best_Path(start, dest); } cin.get(); return 0; }

  36. Program in Action

More Related