Dijkstra's Algorithm Using a Weighted Graph 1. Objective You will be able to: Describe an ADT for a weighted graph. Implement an ADT for a weighted graph.

Presentation on theme: "Dijkstra's Algorithm Using a Weighted Graph 1. Objective You will be able to: Describe an ADT for a weighted graph. Implement an ADT for a weighted graph."— Presentation transcript:

Dijkstra's Algorithm Using a Weighted Graph 1

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. 2

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 3

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" 4

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. 5

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

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 8

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 9

Weighted_Graph.h #pragma once #ifndef MAX_NODES #define MAX_NODES 100 #endif using namespace std; template 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; }; 10

Implementation Constructor template Weighted_Graph ::Weighted_Graph() : number_of_nodes(0) {}; 11

Add_Node template void Weighted_Graph ::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; } 12

Add_Edge template void Weighted_Graph ::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 13

Get_Node_ID template int Weighted_Graph ::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; } 14

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

Display template void Weighted_Graph ::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; } 16

Weighted_Graph.h Add at top: #include 17

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

main.cpp #include #include "Weighted_Graph.h" using namespace std; Weighted_Graph connections; 19

Program Running 21

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) 22

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 23

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. 24

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. 25

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. 26

Best_Path Add to Weighted_Graph class defintion: #include public:... deque 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 27

Best_Path // Dijkstra's Algorithm template deque Weighted_Graph ::Best_Path(const T& Start, const T& Dest) const { deque 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 } 28

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; 29

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; } 30

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 far for this node is the actual // best total distance. int n = best_node_id; best_total_distance_is_known[n] = true; 31

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; } 32

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; } 33

main.cpp void Show_Best_Path(string Start, string Dest) { deque 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; } 34

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; } 35

Program in Action 36

Download ppt "Dijkstra's Algorithm Using a Weighted Graph 1. Objective You will be able to: Describe an ADT for a weighted graph. Implement an ADT for a weighted graph."

Similar presentations