C++ find the second shortest path using Dijkstras algorithm? - c++

I have a Dijkstras algorithm program below. My program reads a text file and finds the shortest path from the start node to the goal node. My question is once this shorest path is discovered, given my code, how can I store this path? Reason being I am required to also find the second shorest path. Thankyou
#include <iostream>
#include <fstream>
#include <vector>
#include <limits.h>
#include <stdio.h>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <utility>
using namespace std;
#define INFINITY1 9999
int counter = 0;
int vcount = 0;
int ecount = 0;
int startVertex;
int endVertex;
int nVerticies;
int nEdges;
struct Vertex
{
int label;
int xcord;
int ycord;
};
struct Edge
{
int parent1;
int parent2;
int weight;
};
Vertex *vertArray = NULL;
Edge *edgeArray = NULL;
float distance(int x1, int y1, int x2, int y2)
{
// Calculating distance
return sqrt(pow(x2 - x1, 2) +
pow(y2 - y1, 2) * 1.0);
}
// Dijkstras
void dijkstra(vector<vector<int>> G, int n, int startnode)
{
// Get x and y cords of start node
int startx = vertArray[startnode].xcord;
int starty = vertArray[startnode].ycord;
// Get x and y cords of end node
int endx = vertArray[n].xcord;
int endy = vertArray[n].ycord;
int **cost = new int *[nVerticies];
for (int i = 0; i < nVerticies; ++i)
{
cost[i] = new int[nVerticies];
}
int distance[nVerticies], pred[nVerticies];
int visited[nVerticies], counter, mindistance, nextnode, i, j;
for (i = 0; i < nVerticies; i++)
for (j = 0; j < nVerticies; j++)
// If there is no weight, then set it to infinity
if (G[i][j] == 0)
cost[i][j] = INFINITY1;
else
{
cost[i][j] = G[i][j];
}
for (i = 0; i < nVerticies; i++)
{
distance[i] = cost[startnode][i];
pred[i] = startnode;
visited[i] = 0;
}
distance[startnode] = 0;
visited[startnode] = 1;
counter = 1;
while (counter < nVerticies - 1)
{
mindistance = INFINITY1;
for (i = 0; i < nVerticies; i++)
if (distance[i] < mindistance && !visited[i])
{
mindistance = distance[i];
nextnode = i;
}
visited[nextnode] = 1;
for (i = 0; i < nVerticies; i++)
if (!visited[i])
if (mindistance + cost[nextnode][i] < distance[i])
{
distance[i] = mindistance + cost[nextnode][i];
pred[i] = nextnode;
}
counter++;
}
for(i=n; i<n+1; i++)
if(i!=startnode)
{
cout<<"\nDistance of node "<<i+1<<"="<<distance[i];
cout<<"\nPath="<<i+1;
j=n;
do
{
j=pred[j+1];
cout<<"<-"<<j+1;
}
while(j!=startnode);
}
}
int main()
{
// Declaration for reading file
int a, b, c;
ifstream readFile;
string fileName;
// Ask for file name
cout << "Enter filename: ";
cin >> fileName;
readFile.open(fileName);
// Read last line and set start and goal vertex equal to file input
while (readFile >> startVertex >> endVertex)
{
}
readFile.close();
readFile.open(fileName);
// Read line 1 and set nVerticies and nEdges equal to file input
while (readFile >> nVerticies >> nEdges)
{
counter++;
break;
}
// Create array with size nVerticies
vertArray = new Vertex[nVerticies];
for (int i = 0; i < nVerticies; i++)
{
// Initialise all elements to zero
vertArray[i].label = 0;
vertArray[i].xcord = 0;
vertArray[i].ycord = 0;
}
// Create array with size nEdges
edgeArray = new Edge[nEdges];
for (int i = 0; i < nEdges; i++)
{
// Initialise all elements to zero
edgeArray[i].parent1 = 0;
edgeArray[i].parent2 = 0;
edgeArray[i].weight = 0;
}
vector<vector<int>> G(nVerticies, vector<int>(nVerticies, 0));
while (readFile >> a >> b >> c)
{
// Get vertex from file and add it to array
if (nVerticies >= counter)
{
vertArray[vcount].label = a;
vertArray[vcount].xcord = b;
vertArray[vcount].ycord = c;
vcount++;
counter++;
}
// Get edge from file and add it to array
else
{
G[a - 1][b - 1] = c;
G[b - 1][a - 1] = c;
edgeArray[ecount].parent1 = a;
edgeArray[ecount].parent2 = b;
edgeArray[ecount].weight = c;
ecount++;
counter++;
}
}
readFile.close();
dijkstra(G, endVertex - 1, startVertex - 1);
int n = 11;
int u = 0;
cout << endl;
cout << endl;
cout << endl;
return 0;
}
output from read file
Distance of node 1=46
Path=1<-2
Distance of node 3=65
Path=3<-1<-2
Distance of node 4=47
Path=4<-2
Distance of node 5=36
Path=5<-2
Distance of node 6=53
Path=6<-2
Distance of node 7=135
Path=7<-8<-6<-2
Distance of node 8=99
Path=8<-6<-2
Distance of node 9=95
Path=9<-4<-2
Distance of node 10=82
Path=10<-2
Distance of node 11=116
Path=11<-10<-2
Distance of node 12=76
Path=12<-2
Distance of node 13=85
Path=13<-2
Ive been guided to follow a similar pattern to the following
if you have a path of 1-->2 -->3 -->4
Set 2 to max and try again
Reset 2
Set 3 to max
Reset 3

Related

Break error on cout

I'm writing an easy Game Of Life simulator. Everything works smoothly except at the very end, when the result is printed by cout I get a break error. I don't understand why and I would like to ask for your help.
variables
#include <iostream>
using namespace std;
struct cell
{
bool isAlive;
int posX;
int posY;
int numberOfAliveNeighbours;
char group;
};
int cellNumber;
cell *cellTable = new cell[cellNumber];
int numberOfTunrs;
main:
int main()
{
int x;
int y;
int cellCounter = 0;
cin >> x >> y;
cellNumber = x*y;
cin >> numberOfTunrs;
for (int i = 0; i < x; i++)
{
for (int j = 0; j < y; j++)
{
char cellAliveChar;
cin >> cellAliveChar;
if (cellAliveChar == '#')
{
cellTable[cellCounter].isAlive = true;
}
else if (cellAliveChar == '.')
{
cellTable[cellCounter].isAlive = false;
}
cellTable[cellCounter].numberOfAliveNeighbours = 0;
cellTable[cellCounter].group = '#';
cellTable[cellCounter].posX = j;
cellTable[cellCounter].posY = i;
cellCounter++;
}
}
doTurns(x, y);
int result;
result = countGroups();
**cout << result << endl;**
//here is breakpoint
cin >> x;
}
countGroups (idk if it's relevant):
int countGroups()
{
int max = 0;
int current;
int i = 0;
char checkingGroup = 'A';
do
{
current = 0;
for (int j = 0; j < cellNumber; j++)
{
if (cellTable[j].group == checkingGroup + i)
{
current++;
}
}
i++;
if (current > max)
{
max = current;
}
} while (current != 0);
return max;
}
the breakpoint screenshot:
Click to view the screenshot
The problem is cellTable declaration:
int cellNumber;
cell *cellTable = new cell[cellNumber];
Global variables are implicitly initialized with 0 so cellNumber will point to array of 0 size and any attempt to access cellTable items leads to undefined behavior.
It would be better to make all variables local and pass them to functions explicitly. Instead of manually allocating array you should use std::vector, or at least allocate after assigning an appropriate number to cellNumber (after getting x and y values).

c++ - Segmentation fault for class function of vector of custom class

I am using following code to run kmeans algorithm on Iris flower dataset- https://github.com/marcoscastro/kmeans/blob/master/kmeans.cpp
I have modified the above code to read input from files. Below is my code -
#include <iostream>
#include <vector>
#include <math.h>
#include <stdlib.h>
#include <time.h>
#include <algorithm>
#include <fstream>
using namespace std;
class Point
{
private:
int id_point, id_cluster;
vector<double> values;
int total_values;
string name;
public:
Point(int id_point, vector<double>& values, string name = "")
{
this->id_point = id_point;
total_values = values.size();
for(int i = 0; i < total_values; i++)
this->values.push_back(values[i]);
this->name = name;
this->id_cluster = -1;
}
int getID()
{
return id_point;
}
void setCluster(int id_cluster)
{
this->id_cluster = id_cluster;
}
int getCluster()
{
return id_cluster;
}
double getValue(int index)
{
return values[index];
}
int getTotalValues()
{
return total_values;
}
void addValue(double value)
{
values.push_back(value);
}
string getName()
{
return name;
}
};
class Cluster
{
private:
int id_cluster;
vector<double> central_values;
vector<Point> points;
public:
Cluster(int id_cluster, Point point)
{
this->id_cluster = id_cluster;
int total_values = point.getTotalValues();
for(int i = 0; i < total_values; i++)
central_values.push_back(point.getValue(i));
points.push_back(point);
}
void addPoint(Point point)
{
points.push_back(point);
}
bool removePoint(int id_point)
{
int total_points = points.size();
for(int i = 0; i < total_points; i++)
{
if(points[i].getID() == id_point)
{
points.erase(points.begin() + i);
return true;
}
}
return false;
}
double getCentralValue(int index)
{
return central_values[index];
}
void setCentralValue(int index, double value)
{
central_values[index] = value;
}
Point getPoint(int index)
{
return points[index];
}
int getTotalPoints()
{
return points.size();
}
int getID()
{
return id_cluster;
}
};
class KMeans
{
private:
int K; // number of clusters
int total_values, total_points, max_iterations;
vector<Cluster> clusters;
// return ID of nearest center (uses euclidean distance)
int getIDNearestCenter(Point point)
{
double sum = 0.0, min_dist;
int id_cluster_center = 0;
for(int i = 0; i < total_values; i++)
{
sum += pow(clusters[0].getCentralValue(i) -
point.getValue(i), 2.0);
}
min_dist = sqrt(sum);
for(int i = 1; i < K; i++)
{
double dist;
sum = 0.0;
for(int j = 0; j < total_values; j++)
{
sum += pow(clusters[i].getCentralValue(j) -
point.getValue(j), 2.0);
}
dist = sqrt(sum);
if(dist < min_dist)
{
min_dist = dist;
id_cluster_center = i;
}
}
return id_cluster_center;
}
public:
KMeans(int K, int total_points, int total_values, int max_iterations)
{
this->K = K;
this->total_points = total_points;
this->total_values = total_values;
this->max_iterations = max_iterations;
}
void run(vector<Point> & points)
{
if(K > total_points)
return;
vector<int> prohibited_indexes;
printf("Inside run \n");
// choose K distinct values for the centers of the clusters
printf(" K distinct cluster\n");
for(int i = 0; i < K; i++)
{
while(true)
{
int index_point = rand() % total_points;
if(find(prohibited_indexes.begin(), prohibited_indexes.end(),
index_point) == prohibited_indexes.end())
{
printf("i= %d\n",i);
prohibited_indexes.push_back(index_point);
points[index_point].setCluster(i);
Cluster cluster(i, points[index_point]);
clusters.push_back(cluster);
break;
}
}
}
int iter = 1;
printf(" Each point to nearest cluster\n");
while(true)
{
bool done = true;
// associates each point to the nearest center
for(int i = 0; i < total_points; i++)
{
int id_old_cluster = points[i].getCluster();
int id_nearest_center = getIDNearestCenter(points[i]);
if(id_old_cluster != id_nearest_center)
{
if(id_old_cluster != -1)
clusters[id_old_cluster].removePoint(points[i].getID());
points[i].setCluster(id_nearest_center);
clusters[id_nearest_center].addPoint(points[i]);
done = false;
}
}
// recalculating the center of each cluster
for(int i = 0; i < K; i++)
{
for(int j = 0; j < total_values; j++)
{
int total_points_cluster = clusters[i].getTotalPoints();
double sum = 0.0;
if(total_points_cluster > 0)
{
for(int p = 0; p < total_points_cluster; p++)
sum += clusters[i].getPoint(p).getValue(j);
clusters[i].setCentralValue(j, sum / total_points_cluster);
}
}
}
if(done == true || iter >= max_iterations)
{
cout << "Break in iteration " << iter << "\n\n";
break;
}
iter++;
}
// shows elements of clusters
for(int i = 0; i < K; i++)
{
int total_points_cluster = clusters[i].getTotalPoints();
cout << "Cluster " << clusters[i].getID() + 1 << endl;
for(int j = 0; j < total_points_cluster; j++)
{
cout << "Point " << clusters[i].getPoint(j).getID() + 1 << ": ";
for(int p = 0; p < total_values; p++)
cout << clusters[i].getPoint(j).getValue(p) << " ";
string point_name = clusters[i].getPoint(j).getName();
if(point_name != "")
cout << "- " << point_name;
cout << endl;
}
cout << "Cluster values: ";
for(int j = 0; j < total_values; j++)
cout << clusters[i].getCentralValue(j) << " ";
cout << "\n\n";
}
}
};
int main(int argc, char *argv[])
{
srand(time(NULL));
int total_points, total_values, K, max_iterations, has_name;
ifstream inFile("datafile.txt");
if (!inFile) {
cerr << "Unable to open file datafile.txt";
exit(1); // call system to stop
}
inFile >> total_points >> total_values >> K >> max_iterations >> has_name;
cout << "Details- \n";
vector<Point> points;
string point_name,str;
int i=0;
while(inFile.eof())
{
string temp;
vector<double> values;
for(int j = 0; j < total_values; j++)
{
double value;
inFile >> value;
values.push_back(value);
}
if(has_name)
{
inFile >> point_name;
Point p(i, values, point_name);
points.push_back(p);
i++;
}
else
{
inFile >> temp;
Point p(i, values);
points.push_back(p);
i++;
}
}
inFile.close();
KMeans kmeans(K, total_points, total_values, max_iterations);
kmeans.run(points);
return 0;
}
Output of code is -
Details-
15043100000Inside run
K distinct cluster i= 0
Segmentation fault
When I run it in gdb, the error shown is -
Program received signal SIGSEGV, Segmentation fault.
0x0000000000401db6 in Point::setCluster (this=0x540, id_cluster=0)
at kmeans.cpp:41
41 this->id_cluster = id_cluster;
I am stuck at this as I cannot find the cause for this segmentation fault.
My dataset file looks like -
150 4 3 10000 1
5.1,3.5,1.4,0.2,Iris-setosa
4.9,3.0,1.4,0.2,Iris-setosa
4.7,3.2,1.3,0.2,Iris-setosa
. . .
7.0,3.2,4.7,1.4,Iris-versicolor
6.4,3.2,4.5,1.5,Iris-versicolor
6.9,3.1,4.9,1.5,Iris-versicolor
5.5,2.3,4.0,1.3,Iris-versicolor
6.5,2.8,4.6,1.5,Iris-versicolor
. . .
in KMeans::run(vector<Point>&) you call points[index_point].setCluster(i); without any guarantee that index_point is within bounds.
index_point is determined by int index_point = rand() % total_points;, and total_points is retrieved from the input file "datafile.txt" which could be anything. It certainly does not have to match points.size(), but it should. Make sure it does, or just use points.size() instead.
A bit offtopic, but using rand() and only using modulo is almost always wrong. If you use C++11 or newer, please consider using std::uniform_int_distribution.
points[index_point].setCluster(i); could be accessing the vector out of bounds. The code you quoted actually always sets a number of total_points in the vector points before calling run, while your modified code just reads until end of file and has no guarantees that the number of total points passed to the constructor of KMeans matches the value of entries in points. Either fix your file I/O or fix the logic of bounds checking.

Dijkstra's algorithm: How to improve memory performance of my implementation

I have been struggling to improve the memory performance of this implementation of Dijkstra's algorithm. Do you have any tips on how to improve this while still using the same data structures and loops?
I basically used an implementation from a Cornell Univ lecture:https://www.cs.cornell.edu/~wdtseng/icpc/notes/graph_part2.pdf
#include <iostream>
#include <stdio.h>
#include <vector>
#include <limits.h>
#include <utility>
#include <list>
#include <set>
#include<bits/stdc++.h>
using namespace std;
int graph[10000][10000];
void dijkstra(int src_node, int num_nodes, int dist[], bool done[]) ;
int main()
{
int num_nodes, num_edges;
cin >> num_nodes >> num_edges;
for(int i = 1; i <= num_nodes; i++)
{
int src, dest, weight;
cin >> src >> dest >> weight;
graph[src][dest] = weight;
}
int src_node = 1;
int dist[num_nodes];
bool done[num_nodes];
dijkstra(src_node, num_nodes, dist,done);
for(int p = 2; p <= num_nodes; p++)
{
cout << dist[p] << " " ;
}
return 0;
}
void dijkstra(int src_node, int num_nodes, int dist[], bool done[])
{
// set all distances to infinity and set all visits to false
for( int i = 1; i <= num_nodes; i++ )
{
dist[i] = INT_MAX;
done[i] = false;
}
dist[src_node] = 0;
while(true)
{
// find the vertex with the smallest dist[] value
int cur_node = -1;
int bestDist = INT_MAX;
//
for( int i = 1; i <= num_nodes; i++ )
{
if( !done[i] && dist[i] < bestDist )
{
cur_node = i;
bestDist = dist[i];
}
}
// if the best distance is infinity, break out of the loop
if( bestDist == INT_MAX )
{
break;
}
// iterate through all the neighbors
for( int adj_node = 1; adj_node <= num_nodes; adj_node++ )
{
// if the adj node has not been visited and has a weight
if( !done[adj_node] && graph[cur_node][adj_node] != NULL )
{
// if the distance of the adj node is greater
if( dist[adj_node] > dist[cur_node] + graph[cur_node][adj_node])
{
// make the dist = to curr node distance + weight
dist[adj_node] = dist[cur_node] + graph[cur_node][adj_node];
}
}
}
// mark current node as done
done[cur_node] = true;
}
}

Need assistance with Segmentation Error

The following code is giving me the following error
Error description :
Unhandled exception at 0x00DC5D81 in ImageComponent2.exe: 0xC0000005: Access violation reading location 0xCDCDCDD5.
// ImageComponents
#include <iostream>
#include "Position.h"
using namespace std;
void labelComponents(int size, int **pixel);
void outputImage(int size, int **pixel);
int main(){
int size = 0;
cout << "Enter image size: ";
cin >> size;
int ** pixel = new int *[size + 2];
for (int i = 1; i <= size; i++)
{
pixel[i] = new int[size + 2];
}
cout << "Enter the pixel array in row-major order:\n";
for (int i = 1; i <= size; i++)
for (int j = 1; j <= size; j++)
{
cin >> pixel[i][j];
}
labelComponents(size, pixel);
outputImage(size, pixel);
system("pause");
return (0);
}
void labelComponents(int size, int **pixel){
// initialize offsets
Position * offset = new Position[4];
offset[0] = Position(0, 1); // right
offset[1] = Position(1, 0); // down
offset[2] = Position(0, -1); // left
offset[3] = Position(-1, 0); // up
int numNbr = 4; // neighbors of a pixel position
Position * nbr = new Position(0, 0);
Position * Q = new Position[size * size];
int id = 1; // component id
int x = 0; // (Position Q)
// scan all pixels labeling components
for (int r = 1; r <= size; r++) // row r of image
for (int c = 1; c <= size; c++) // column c of image
{
if (pixel[r][c] == 1)
{// new component
pixel[r][c] = ++id; // get next id
Position * here = new Position(r, c);
do
{// find rest of component
for (int i = 0; i < numNbr; i++)
{// check all neighbors of here
nbr->setRow(here->getRow() + offset[i].getRow());
nbr->setCol(here->getCol() + offset[i].getCol());
if (pixel[nbr->getRow()][nbr->getCol()] == 1)
{// pixel is part of current component
pixel[nbr->getRow()][nbr->getCol()] = id;
Q[x] = *nbr;
x++;
}
}
// any unexplored pixels in component?
*here = Q[x]; // a component pixel
x--;
} while (here != NULL);
} // end of if, for c, and for r
}
} // end of labelComponents
void outputImage(int size, int **pixel){
cout << "The labeled image is: ";
for (int i = 1; i <= size; i++){
cout << endl;
for (int j = 1; j <= size; j++)
cout << pixel[i][j] << " ";
}
} // end of outputImage
//Position.h
#ifndef POSITION_H
#define POSITION_H
class Position
{
private:
int row; // row number of the position
int col;
// column number of the position
public:
Position(); // default
Position( int theRow, int theCol); // parameter
Position(const Position & aPosition); // copy
Position & operator = (const Position & aPosition); // overload =
// overload =
// mutators
void setRow (int r);
void setCol (int c);
//accessors
int getRow() const;
int getCol() const;
}; // end Position
Position::Position()
{
setRow(0);
setCol(0);
}
Position::Position(int r, int c)
{
setRow(r);
setCol(c);
}
Position::Position(const Position & aPosition)
{
setRow(aPosition.row);
setCol(aPosition.col);
}
Position & Position::operator=(const Position & aPosition)
{
this->row=aPosition.row;
this->col=aPosition.col;
return(*this);
}
void Position::setRow(int r)
{
this->row = r;
}
void Position::setCol(int c)
{
this->col = c;
}
int Position::getRow() const
{
return this->row;
}
int Position::getCol() const
{
return this->col;
}
#endif
In C/C++, arraw indexes go from 0 to n-1, not from 1 to n. All your for loops are wrong:
for (int i = 1; i <= size; i++)
Must be replaced by:
for (int i = 0; i < size; i++)
Else, you access array at sizeposition which is out of bound.
Using a debugger and/or working with smaller piece of code would have made it easier for you to figure this out ;-)

Subgraph with max nodes

I have the graph with N nodes. I have to create the longest subgraph (with max nodes). One node can be connected with only 2 nodes. So which nodes should I take to create this (max) subgraph?
What I'm doing is:
1: From initial node. I start 2 DFS functions. (from anothers nodes only 1).
2: For some node in DFS I use F() function to check all neighbours and find maximum way that I have to go. Then I'm saving the index of the node in which I have to go in index variable and starting DFS from index.
The problem is that this algorithm is too slow. How can I optimize it? Maybe there is special algorithm to find maximum subgraph?
Here is my code:
#include <stdio.h>
#include <cstring>
#include <algorithm>
#include <iostream>
using namespace std;
int used[20];
int m[20][20];
int c;
int F(int v) {
used[v] = 1;
int maxn = 0, index = -1, t;
for(int i = 0; i < c; ++i) {
if(!used[i] && m[v][i] == 1) {
t = F(i);
if(t > maxn) {
maxn = t;
index = i;
}
}
}
if(index != -1) {
used[v] = 0;
return maxn + 1;
}
else {
used[v] = 0;
return 1;
}
}
int DFS(int v) {
used[v] = 1;
int maxn = 0, index = -1, t;
for(int i = 0; i < c; ++i) {
if(!used[i] && m[v][i] == 1) {
t = F(i);
if(t > maxn) {
maxn = t;
index = i;
}
}
}
if(index != -1) {
return DFS(index) + 1;
}
else {
return 0;
}
}
int main() {
cin >> c;
for(int i = 0; i < c; ++i) {
for(int j = 0; j < c; ++ j)
cin >> m[i][j];
}
int maxn = DFS(0) + DFS(0) + 1;
cout << maxn << endl;
}