Skip to content

Instantly share code, notes, and snippets.

@prespondek
Last active January 29, 2018 11:22
Show Gist options
  • Save prespondek/e6de307ecf07297c63fe to your computer and use it in GitHub Desktop.
Save prespondek/e6de307ecf07297c63fe to your computer and use it in GitHub Desktop.
Dijkstra's Algorithm
#include <vector>
#include <queue>
#include <math.h>
template<typename T>
class Dijkstra
{
public:
class GraphEdge;
struct GraphVertex
{
friend class Dijkstra;
T data;
void addEdge(GraphVertex* vert, float score) {
GraphEdge edge;
edge.next = vert;
edge.weight = score;
edges.push_back(edge);
}
std::vector<GraphEdge> edges;
protected:
float score;
bool visited = false;
};
struct GraphEdge
{
friend class Dijkstra;
GraphVertex* next;
float weight;
};
GraphVertex* createVertex ()
{
auto vert = new Dijkstra<T>::GraphVertex ();
vertices.push_back(vert);
return vert;
}
virtual ~Dijkstra () {
for ( auto vert : vertices ) {
delete vert;
}
}
float calcPath(GraphVertex* start, GraphVertex* target, std::vector<GraphVertex*>* path)
{
if (start == target) return 0;
// graph vertices go into a priority queue with lowest score at the top
std::priority_queue<GraphVertex*, std::vector<GraphVertex*>, compareRange> queue;
for ( auto& vertex : vertices ) {
vertex->score = MAXFLOAT;
vertex->visited = false;
}
start->score = 0;
queue.push(start);
bool found = false;
while (!queue.empty()) {
GraphVertex* top = queue.top();
if (top == target) {
found = true;
break;
}// break out of the loop if we have reached the target
queue.pop();
if (top->visited == true) continue; // skip over vertices that have alread been visited
for ( auto& edge : top->edges ) {
if (edge.next->visited == false) {
if (edge.next->score > (top->score + edge.weight)) {
edge.next->score = top->score + edge.weight;
}
queue.push(edge.next);
top->visited = true;
}
}
}
if (!found) return MAXFLOAT;
// our graph is primed so lets get the path back to the source vertex
GraphVertex* node = target;
if (path) {
path->push_back(node);
while (node != start) {
for ( auto& edge : node->edges ) {
if (node->score > edge.next->score) {
node = edge.next;
}
}
path->push_back(node);
}
std::reverse(path->begin(), path->end());
}
return target->score;
}
std::vector<GraphVertex*> vertices;
struct compareRange {
bool operator () (const GraphVertex* a, const GraphVertex* b) {
return (a->score > b->score);
}
};
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment