I have implemented Dijkstra's algorithm in C++, but it seems a bit complicated since I really tried to follow the process of the algorithm as much as I could. If there's any simplification you would suggest, I would really appreciate, because this task was only for me to get familiarized with this method before the A* algorithm. The whole class thing about the nodes might be unnecesary, but I really like to think of these objects and to treat them like real things.
EDIT: I noticed I should've added a field that shows whether a node is open or not, in order to eliminate pushing the same node twice to the priority queue.
#include <iostream>
#include <vector>
#include <fstream>
#include <queue>
#include <climits>
using namespace std;
class Node {
int label;
int d; // Overall distance from the start point
bool processed; // Visited node indicator
Node* parent;
vector<Node*> neighbors;
vector<int> dist; // Distance from each heighbor
public:
Node(int = 0);
void addNeighbor(Node*);
void addDist(int);
void setLabel(int);
void setD(int);
void setProccessed(bool);
void setParent(Node*);
int getLabel();
int getD();
bool isProcessed();
Node* getParent();
vector<Node *> getNeighbors();
vector<int> getDist();
};
Node::Node(int label) {
this->label = label;
}
void Node::addNeighbor(Node* neighbor) {
neighbors.push_back(neighbor);
}
void Node::addDist(int d) {
dist.push_back(d);
}
void Node::setLabel(int label) {
this->label = label;
}
void Node::setD(int d) {
this->d = d;
}
void Node::setParent(Node* node) {
parent = node;
}
void Node::setProccessed(bool p) {
processed = p;
}
int Node::getLabel() {
return label;
}
int Node::getD() {
return d;
}
Node* Node::getParent() {
return parent;
}
bool Node::isProcessed() {
return processed;
}
vector<Node*> Node::getNeighbors() {
return neighbors;
}
vector<int> Node::getDist() {
return dist;
}
void init(ifstream& f, Node**& nodes, int& n) {
f >> n;
nodes = new Node*[n];
int** adj = new int*[n];
for (int i = 0; i < n; i++) {
adj[i] = new int[n];
}
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
adj[i][j] = 0;
}
}
int label, start, end, weight;
while(f >> start >> end >> weight) {
adj[start - 1][end - 1] = weight;
adj[end - 1][start - 1] = weight;
}
for (int i = 0; i < n; i++) {
nodes[i] = new Node(i + 1);
}
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
{
if (adj[i][j] != 0)
{
nodes[i]->addNeighbor(nodes[j]);
nodes[i]->addDist(adj[i][j]);
}
}
}
for (int i = 0; i < n; i++) {
delete[] adj[i];
}
delete[] adj;
}
void initNodes(Node** nodes, int n) {
for (int i = 0; i < n; i++) {
nodes[i]->setD(INT_MAX);
nodes[i]->setParent(NULL);
nodes[i]->setProccessed(false);
}
}
class Compare {
public:
bool operator()(Node* n1, Node* n2) {
return n1->getD() > n2->getD();
}
};
void writePath(Node* node) {
if (node) {
int label = node->getLabel();
node = node->getParent();
writePath(node);
if(node) {
cout << " -> ";
}
cout << label;
}
}
void dijkstra(Node** nodes, int n) {
cout << "Dijkstra algorithm" << endl;
int start = 1;
int end = 7;
initNodes(nodes, n);
nodes[start - 1]->setD(0);
priority_queue<Node*, vector<Node*>, Compare> queue;
queue.push(nodes[start - 1]);
Node* current;
do {
current = queue.top();
queue.pop();
current->setProccessed(true);
vector<Node *> neighbors = current->getNeighbors();
for (unsigned int i = 0; i < neighbors.size(); i++) {
if((!neighbors.at(i)->isProcessed())) {
if((neighbors.at(i)->getD() == INT_MAX || (current->getD() + current->getDist().at(i) < neighbors.at(i)->getD()))) {
neighbors.at(i)->setParent(current);
neighbors.at(i)->setD(current->getD() + current->getDist().at(i));
}
queue.push(neighbors.at(i));
}
}
} while(current->getLabel() != end);
/*
*/
writePath(current);
cout << endl;
}
int main() {
ifstream f("input.in");
int numOfNodes;
Node** nodes;
init(f, nodes, numOfNodes);
for (int i = 0; i < numOfNodes; i++) {
vector<Node *> neighbors = nodes[i]->getNeighbors();
cout << i + 1 << ": ";
for (int j = 0; j < neighbors.size(); j++) {
cout << neighbors[j]->getLabel() << " ";
}
cout << endl;
}
cout << endl;
dijkstra(nodes, numOfNodes);
for (int i = 0; i < numOfNodes; i++) {
delete nodes[i];
}
delete[] nodes;
return 0;
}
INPUT:
8
1 3 2
1 4 4
2 3 3
2 5 4
2 6 5
3 4 1
5 7 6
5 8 3
6 7 5
7 8 1