dijkstra.cc.html
//**************************************************************************
#include <iostream.h>
#include <limits.h>
#include <string.h>
#include "vertex.h"
#include "priqueue.h"
#include "adjlist.h"
#include "hash.h"
#include "dijkstra.h"
//**************************************************************************
// Implementation of dijkstra's algorithm, accepts graph G as input
// Returns array of vertices V forming shortest path edges
void dijkstra(int source, AdjList& G, Vertex *V, HashTable& T, int print_heap)
{
int i;
int num_vert = G.no_of_verts();
PriQueue Q(num_vert); // Declares a Priority queue
G.setDist(source,0);
G.setKnown(source,1);
// Initializes queue for edges from source to all others
Vertex *vert = G.start(source);
while (vert)
{
Vertex adder(vert->name,source,vert->distance);
Q.Insert(adder);
G.setDist(vert->name,vert->distance);
vert = vert->next;
}
// INT_MAX is used for no edge between two vertices
for (i=1;i<=num_vert;i++)
{
if (i != source && !Q.IsThere(i))
{
Vertex adder(i,source,INT_MAX);
Q.Insert(adder);
}
}
for (i=1;i<=num_vert-1;i++)
{
if (print_heap) Print_Heap(Q,T);
Vertex min = Q.Delete_Min(); // Removes the smallest edge
V[min.name-1] = min; // And adds it to array V
V[min.name-1].distance = G.distance(min.name)-G.distance(min.parent);
G.setKnown(min.name,1);
Vertex *vert = G.start(min.name);
if (min.distance != INT_MAX)
while (vert)
{
if (!G.Known(vert->name))
{
int dist = vert->distance;
int new_weight = min.distance + dist;
if (new_weight < G.distance(vert->name))
{
G.setDist(vert->name,new_weight);
Q.Decrease_Key(vert->name,new_weight,min.name);
}
}
vert = vert->next;
}
}
if (print_heap) cout << endl;
}
//**************************************************************************
// Prints the Path from "source" to "dest"
void Print_Path (int source, int dest, Vertex *V, AdjList& G, HashTable& T)
{
cout << endl;
if (dest == source)
{
cout << '\t' << T.name_of(dest) << " is the source !!" << endl
<< endl;
return;
}
int total = 0;
Print_Path_Rec(source,dest,V,G,T,&total);
if (total != INT_MAX)
cout << '\t' << "total cost: " << total << endl;
cout << endl;
}
//**************************************************************************
// Recursive routine called by Print_Path
void Print_Path_Rec (int source, int dest, Vertex *V, AdjList& G,
HashTable& T, int *total)
{
int dist = V[dest-1].distance;
if (dist == INT_MAX)
{
cout << '\t' << "Cannot get to " << T.name_of(dest) << "." << endl;
*total = dist;
return;
}
if (V[dest-1].parent != source)
Print_Path_Rec(source,V[dest-1].parent,V,G,T,total);
cout << '\t' << T.name_of(V[dest-1].parent) << " -> "
<< T.name_of(V[dest-1].name)
<< " " << dist << endl;
*total += dist;
return;
}
//**************************************************************************
void Print_Dijkstra (int source, Vertex *V, HashTable& T)
{
cout << "Shortest paths computed by Dijkstra's algorithm with focus \""
<< T.name_of(source) << "\" ->" << endl;
cout << endl;
for (int i=0;i<T.nodes_of();i++)
if (i != (source-1))
{
cout << '\t' << T.name_of(V[i].parent) << " to "
<< T.name_of(V[i].name) << " -> ";
if (V[i].distance != INT_MAX)
cout << V[i].distance << endl;
else
cout << "Unreachable" << endl;
}
cout << endl;
}
//**************************************************************************
void Print_Heap (PriQueue& Q, HashTable& T)
{
cout << "Heap[" << Q.getSize() << "] -> ";
for (int i=1;i<=Q.getSize();i++)
{
cout << "(" << T.name_of(Q.getName(i)) << ",";
if (Q.getWeight(i) != INT_MAX)
cout << Q.getWeight(i);
else
cout << "Inf";
cout << ") ";
}
cout << endl;
}
//**************************************************************************