programming-examples/c++/Others/Graph1.cpp - Shortest path program using STL.cpp
2019-11-15 12:59:38 +01:00

219 lines
4.7 KiB
C++

Graph1.cpp - Shortest path program using STL
#pragma warning (disable: 4786)
#include <iostream>
#include <fstream>
#include <sstream>
#include <limits.h>
#include <map>
#include <vector>
#include <string>
#include <stack>
#include <list>
using namespace std;
int INFINITY = INT_MAX;
struct Vertex
{
string name; // Vertex name
vector<Vertex *> adj; // Adjacent vertices
int dist; // Cost
Vertex *path; // Previous vertex on shortest path
Vertex( const string & nm ) : name( nm )
{ reset( ); }
void reset( )
{ dist = INFINITY; path = NULL; }
};
typedef map<string,Vertex *> vmap;
typedef pair<string,Vertex *> vpair;
class Graph
{
public:
Graph( ) { }
~Graph( );
void addEdge( const string & sourceName, const string & destName );
void printPath( const string & destName ) const;
void unweighted( const string & startName );
private:
Vertex * getVertex( const string & vertexName );
void printPath( const Vertex & dest ) const;
void clearAll( );
vmap vertexMap;
vector<Vertex *> allVertices;
};
void Graph::addEdge( const string & sourceName, const string & destName )
{
Vertex * v = getVertex( sourceName );
Vertex * w = getVertex( destName );
v->adj.push_back( w );
}
void Graph::printPath( const string & destName ) const
{
vmap::const_iterator itr = vertexMap.find( destName );
if( itr == vertexMap.end( ) )
{
cout << "Destination vertex not found" << endl;
return;
}
const Vertex & w = *(*itr).second;
if( w.dist == INFINITY )
cout << destName << " is unreachable";
else
printPath( w );
cout << endl;
}
// If vertexName is not present, add it to vertexMap
// In either case, return the Vertex
Vertex * Graph::getVertex( const string & vertexName )
{
vmap::iterator itr = vertexMap.find( vertexName );
if( itr == vertexMap.end( ) )
{
Vertex *newv = new Vertex( vertexName );
allVertices.push_back( newv );
vertexMap.insert( vpair( vertexName, newv ) );
return newv;
}
return (*itr).second;
}
void Graph::printPath( const Vertex & dest ) const
{
if( dest.path != NULL )
{
printPath( *dest.path );
cout << " to ";
}
cout << dest.name;
}
void Graph::clearAll( )
{
for( int i = 0; i < allVertices.size( ); i++ )
allVertices[ i ]->reset( );
}
Graph::~Graph( )
{
for( int i = 0; i < allVertices.size( ); i++ )
delete allVertices[ i ];
}
void Graph::unweighted( const string & startName )
{
clearAll( );
vmap::iterator itr = vertexMap.find( startName );
if( itr == vertexMap.end( ) )
{
cout << startName << " is not a vertex in this graph" << endl;
return;
}
Vertex *start = (*itr).second;
list<Vertex *> q;
q.push_back( start ); start->dist = 0;
while( !q.empty( ) )
{
Vertex *v = q.front( ); q.pop_front( );
for( int i = 0; i < v->adj.size( ); i++ )
{
Vertex *w = v->adj[ i ];
if( w->dist == INFINITY )
{
w->dist = v->dist + 1;
w->path = v;
q.push_back( w );
}
}
}
}
/**
* Process a request; return false if end of file.
*/
bool processRequest( istream & in, Graph & g )
{
string startName;
string destName;
cout << "Enter start node: ";
if( !( in >> startName ) )
return false;
cout << "Enter destination node: ";
if( !( in >> destName ) )
return false;
g.unweighted( startName );
g.printPath( destName );
return true;
}
/**
* A simple main that reads the file given by argv[1]
* and then calls processRequest to compute shortest paths.
* Skimpy error checking in order to concentrate on the basics.
*/
int main( int argc, char *argv[ ] )
{
Graph g;
if( argc != 2 )
{
cerr << "Usage: " << argv[ 0 ] << " graphfile" << endl;
return 1;
}
ifstream inFile( argv[ 1 ] );
if( !inFile )
{
cerr << "Cannot open " << argv[ 1 ] << endl;
return 1;
}
string oneLine;
// Read the words; add them to wordMap
while( getline( inFile, oneLine ) )
{
string source, dest;
istringstream st( oneLine );
st >> source;
st >> dest;
g.addEdge( source, dest );
}
cout << "File read" << endl;
while( processRequest( cin, g ) )
;
return 0;
}