Please review the implementation of Dijkstra algorithms. Points on which I have doubt:
My
Graph
doesn't have any ID for nodes. Nodes are accessed based on their data. Is there any general approach in that? Should nodes be referenced by an ID as that will also make these algo somewhat easier to implement by using id as index into arrays.With current graph representation, are there any issue in the algo implementation?
- Are there any issues in method of accessing vertex and edges
shared_ptr
? Shouldweak_ptr
be used at some places? Anyshared_ptr
validity issue?
Anything that you can suggest to improve will be helpful.
Vertex:
class Vertex {
public:
Vertex() {
bVisited = false;
}
int data = 0;
EdgeList edgeList;
bool bVisited = false;
};
Edge:
struct Edge {
int cost;
boost::weak_ptr<Vertex> srcVertex;
boost::weak_ptr<Vertex> dstVertex;
};
Graph:
typedef std::list<boost::shared_ptr<Vertex>> VerticesList;
typedef std::map<int, VerticesList::const_iterator> DataVertexMap;
class Graph {
VerticesList _verticesList;
DataVertexMap _dataVertexMap;
//TODO: Need some design to have this function internal only and not exposed to client
boost::shared_ptr<Vertex> addAndGetVertex(int data);
public:
Graph();
~Graph();
bool isEmpty() const;
//We don't check for duplicate vertex
void addVertex(int data);
void addEdge(int srcData, int dstData, int cost);
int getCostForEdge(int srcData, int dstData);
void displayGraph();
void dfsTraversal();
void bfsTraversal();
void findShortestPath(int srcData, int dstData);
void kruskalMST();
void primMST();
};
Dijkstra's shortest path implementation:
void Graph::findShortestPath(int srcData, int dstData) {
DataVertexMap::const_iterator srcIter = _dataVertexMap.find(srcData);
DataVertexMap::const_iterator dstIter = _dataVertexMap.find(dstData);
if(srcIter == _dataVertexMap.end() || dstIter == _dataVertexMap.end())
assert(false);
boost::shared_ptr<Vertex> srcVertex(*(srcIter->second));
boost::shared_ptr<Vertex> dstVertex(*(dstIter->second));
struct VertexInfo {
bool bGotMinDistance = false;
boost::weak_ptr<Vertex> precedingVertex;
int distanceFromSource = INFINITY;
};
boost::shared_ptr<Vertex> currentVertex = srcVertex;
typedef std::map<boost::shared_ptr<Vertex>, VertexInfo> VertexInfoMap;
VertexInfoMap vertexInfoMap;
for(boost::shared_ptr<Vertex> vertex : _verticesList) {
VertexInfo info;
if(vertex.get() == srcVertex.get()) {
info.bGotMinDistance = true;
info.distanceFromSource = 0;
info.precedingVertex = boost::weak_ptr<Vertex> ();
}
vertexInfoMap.insert(std::make_pair(vertex, info));
}
while(currentVertex.get() != dstVertex.get()) {
VertexInfo& curVertexInfo = vertexInfoMap[currentVertex];
curVertexInfo.bGotMinDistance = true;
boost::shared_ptr<Vertex> minDistVertex = currentVertex;
int curMinDist = INFINITY;
for(auto iter = vertexInfoMap.begin(); iter != vertexInfoMap.end(); ++iter) {
boost::shared_ptr<Vertex> vertex = iter->first;
VertexInfo& vertexInfo = iter->second;
if(!vertexInfo.bGotMinDistance) {
int distFromCurToVertex = getCostForEdge(currentVertex->data, vertex->data);
if(vertexInfo.distanceFromSource > distFromCurToVertex + curVertexInfo.distanceFromSource) {
vertexInfo.distanceFromSource = distFromCurToVertex + curVertexInfo.distanceFromSource;
vertexInfo.precedingVertex = currentVertex;
}
if(vertexInfo.distanceFromSource < curMinDist) {
curMinDist = vertexInfo.distanceFromSource;
minDistVertex = vertex;
}
}
}
currentVertex = minDistVertex;
}