-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathGraph2.cpp
235 lines (194 loc) · 5.33 KB
/
Graph2.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
#include <iostream.h>
#include <fstream.h>
#include <limits.h>
#ifdef unix
#include <strstream.h>
#else
#include <strstrea.h> // <strstream.h> on UNIX machines
#endif
#include "mystring.h"
#include "SeparateChaining.h"
#include "LinkedList.h"
#include "QueueAr.h"
int INFINITY = INT_MAX;
struct Vertex
{
string name; // Vertex name
List<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; }
};
struct MapEntry
{
string vertexName;
Vertex *storedVertex;
MapEntry( const string & name = "", Vertex * v = NULL )
: vertexName( name ), storedVertex( v ) { }
bool operator!=( const MapEntry & rhs ) const
{ return vertexName != rhs.vertexName; }
bool operator==( const MapEntry & rhs ) const
{ return vertexName == rhs.vertexName; }
};
int hash( const MapEntry & x, int tableSize )
{
return hash( x.vertexName, tableSize );
}
class Graph
{
public:
Graph( ) : vertexMap( MapEntry( ) ), numVertices( 0 ) { }
~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( );
HashTable<MapEntry> vertexMap;
List<Vertex *> allVertices;
int numVertices;
const MapEntry ITEM_NOT_FOUND;
};
void Graph::addEdge( const string & sourceName, const string & destName )
{
Vertex * v = getVertex( sourceName );
Vertex * w = getVertex( destName );
v->adj.insert( w, v->adj.zeroth( ) );
}
void Graph::printPath( const string & destName ) const
{
const MapEntry & match = vertexMap.find( MapEntry( destName ) );
if( match == ITEM_NOT_FOUND )
{
cout << "Destination vertex not found" << endl;
return;
}
const Vertex & w = *match.storedVertex;
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 )
{
static MapEntry entry;
entry.vertexName = vertexName;
const MapEntry & match = vertexMap.find( entry );
if( match == ITEM_NOT_FOUND )
{
entry.storedVertex = new Vertex( vertexName );
allVertices.insert( entry.storedVertex, allVertices.zeroth( ) );
numVertices++;
vertexMap.insert( entry );
return entry.storedVertex;
}
return match.storedVertex;
}
void Graph::printPath( const Vertex & dest ) const
{
if( dest.path != NULL )
{
printPath( *dest.path );
cout << " to ";
}
cout << dest.name;
}
void Graph::clearAll( )
{
ListItr<Vertex *> itr;
for( itr = allVertices.first( ); !itr.isPastEnd( ); itr.advance( ) )
itr.retrieve( )->reset( );
}
Graph::~Graph( )
{
ListItr<Vertex *> itr;
for( itr = allVertices.first( ); !itr.isPastEnd( ); itr.advance( ) )
delete itr.retrieve( );
}
void Graph::unweighted( const string & startName )
{
clearAll( );
const MapEntry & match = vertexMap.find( MapEntry( startName ) );
if( match == ITEM_NOT_FOUND )
{
cout << startName << " is not a vertex in this graph" << endl;
return;
}
Vertex *start = match.storedVertex;
Queue<Vertex *> q( numVertices );
q.enqueue( start ); start->dist = 0;
while( !q.isEmpty( ) )
{
Vertex *v = q.dequeue( );
ListItr<Vertex *> itr;
for( itr = v->adj.first( ); !itr.isPastEnd( ); itr.advance( ) )
{
Vertex *w = itr.retrieve( );
if( w->dist == INFINITY )
{
w->dist = v->dist + 1;
w->path = v;
q.enqueue( 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;
istrstream st( (char *) oneLine.c_str( ) ); // Deprecated form of string streams
st >> source;
st >> dest;
g.addEdge( source, dest );
}
cout << "File read" << endl;
while( processRequest( cin, g ) )
;
return 0;
}