I'm trying to implement Dijkstra's algorithm to find the shortest path from a starting node to the last node of a 250px by 200px raw image file (e.g. starting node = [0][0], ending node = [250][200]). The raw file acts like a topographical map in that each byte represents an elevation and the distance cost from one node to its adjacent node(s) is the difference in elevations of the two nodes plus 1 for the energy to move from one node to its neighbor (movement can only happen horizontally and vertically).
I have followed the pseudocode for the algorithm using a priority queue in C++, but am struggling to debug to see if I have successfully implemented the algorithm correctly as well as implementing the algorithm to accomplish this unique and relatively challenging situation. Also, my goal is to output the shortest path in a raw file and then view it in Photoshop to see if it is being displayed correctly, but have failed completely at this task.
After all that, my questions are:
- Are there any visible/blaring logical errors in my implementation of solving the above described problem?
- Could anyone suggest some ideas on how to try to output the shortest path in a raw file or something along similar lines?
I know I've used file read and write operations with the C notation rather than the stream operations of C++ so there's no need of telling me how I can change that.
#include <iostream>
#include <fstream>
#include <iomanip>
#include <queue>
#define INFINITY 99999
#define MAP_SIZE 50000 // 250px by 200px
void dijkstra(int, int, unsigned int []);
// The terminology 'Node' and 'Vertex' are used interchangeably
// throughout the program.
struct Node
{
int index; // index of node in graph
unsigned int distance; // distance from source (only allow positive distances)
};
// A simple class to compare the distances of two Node structures.
class CompareDist
{
public:
bool operator()(Node& n1, Node& n2)
{
if (n1.distance < n2.distance)
return true;
else
return false;
}
};
int main()
{
FILE *fr = fopen("map.raw","rb");
FILE *fw1 = fopen("path.raw","w+");
int i;
unsigned char read[MAP_SIZE];
unsigned int original[MAP_SIZE]; //2D array implemented in 1D array
unsigned char path[MAP_SIZE];
if(!fr){
std::cout<<"Error: Can't open raw file!"<<std::endl;
return 0;
}
fread(read, sizeof(char), MAP_SIZE, fr);
fclose(fr);
//convert to int for calculation
for (i = 0; i < MAP_SIZE; i++) {
original[i] = (int)((unsigned short)read[i]);
}
dijkstra(0, MAP_SIZE, original);
for (i = 0; i < MAP_SIZE; i++) {
path[i] = (unsigned char)original[i]; // output path array
}
fwrite(&path,sizeof(char),MAP_SIZE,fw1);
fclose(fw1);
return 0;
}
// Implementation of dijkstra's algorithm using a priority queue
// Inputs: int s --> source node
// int size --> the total number of vertices in graph
// unsigned int graph[] --> your graph
// Outputs: nothing
void dijkstra(int source, int size, unsigned int graph[MAP_SIZE])
{
bool *visited = new bool [size]; // array to check which vertices have already been visited
unsigned int *distance = new unsigned int [size]; // table to hold the distances of each vertex from the source vertex
// initialize the distance of each node to infinity and visited as false
for (int i = 0; i < size; i++)
{
distance[i] = INFINITY;
visited[i] = false;
}
// the distance of the source to itself is obviously 0
distance[source] = 0;
// create priority queue structure
std::priority_queue< Node, std::vector< Node >, CompareDist> priorityQ;
// Create the first node as the source and put it into the queue
Node first = { source, 0 };
priorityQ.push(first);
// Pick the top node of priority queue.
// Update the queue with next visited vertex after checking
// which non-visited vertex has the minimum distance from
// the source vertex.
while(!priorityQ.empty())
{
Node tempNode = priorityQ.top();
priorityQ.pop();
int nodeIndex = tempNode.index;
visited[nodeIndex] = true;
for(int i = 0;i < size; i++)
{
if(graph[i] != 0 && !visited[i])
{
// Update the distance if it is smaller than the current distance
int tempDist = distance[nodeIndex] + graph[i] + 1;
if(distance[i] > tempDist)
{
distance[i] = tempDist;
Node newNode;
newNode.index = i;
newNode.distance = distance[i];
priorityQ.push(newNode);
}
}
}
}
// DEBUG TEST FOR CORRECT OUTPUT
std::cout << "The shortest distance from " << source << " to all other nodes is" << std::endl;
for(int i = 0; i < size; i++)
{
std::cout << i << " : " << distance[i] << std::endl;
graph[i] = distance [i];
}
std::cout << std::endl << std::endl;
}