The text file containing the road network is split into two sections. All the locations will be listed first, followed by all the roads.
Here is a sample of how a file might look:
location|203792386|-90.0020975|35.1606029 location|203841564|-90.0142355|35.1582919 location|1782970695|-89.9816435|35.1509496 location|203829293|-89.9948465|35.1590589 ... more lines here ... road|203792386|203848891|45|Jackson Avenue road|203670568|203690459|25|North Idlewild Street road|203659739|203659741|25|Hawthorne Street road|203874737|203874738|25|Tutwiler Avenue road|203785561|203785562|25|Mignon Avenue ... more lines here ...Each line that begins with "location" contains a description of an intersection where at least two roads meet. For each location, you are given a unique integer ID (up to ten digits), then the longitude of the location, then the latitude. The sample road network supplied for this project contain information about the Memphis road network, so all all of the longitudes will be negative numbers very close to -90 because Memphis is in the Western hemisphere. The four parts of each "location" line in the text file are separated by a vertical bar (|).
Note that longitudes come first, then latitudes.
After all of the locations, the file will lists all of the "roads." A road is any sort of straight-line connection between two locations. This covers any kind of surface a car can drive on. Curved roads are approximated by multiple "road" segments, since a single "road" instance only represents a straight line. Each road is described by the identifiers of the locations that it connects, the speed limit on the road (in mph), and the name of the road. The five parts of each "road" line in the text file are separated by a vertical bar (|).
For example, in the file above, the road labeled Jackson Avenue connects the locations with the IDs 203792386 and 203848891, and has a speed limit of 45 miles per hour.
All roads are assumed to be bi-directional (no one-way streets), but each road is only listed once in the file. In other words, if there is a line in the file that looks like
road|x|y|....then there will not be a line that looks like
road|y|x|....even though your program should assume that you can travel in either direction between locations x and y.
There may be more than one "road" in a text file with the same name. In fact, this is quite common, for two reasons. First, a single physical road may be made of made up of multiple straight segments connecting intersections of other roads. Second, a curved road, even if it never intersects any other road, must be approximated by multiple straight segments.
Use these files for testing: west-of-rhodes.txt all-memphis.txt
Efficiency: There should not be a significant delay (< 0.5 second) between the time a user enters a location and the time your program prints back the roads connected to that location. This means that you should choose your graph data structures very carefully, most likely so common operations like adding a new location, adding a new road, or looking up what locations are connected to other locations run in expected constant time, or at worst, logarithmic. The "all-memphis.txt" network contains roughly 50,000 locations and 58,000 roads, so even linear-time operations will likely be too slow. The easiest way to accomplish this is to make use of the map/dictionary data structure (implemented as hash tables). See the hints below for more information.
When your program initially starts, there may be a slightly longer delay (< 5 seconds) while the road network text file is read and processed.
Enter a filename: west-of-rhodes.txt Enter a location or zero to quit: 203744902 Location 203744902 has edges leading to: 203744900 35 mph North McLean Boulevard 203874090 25 mph Lyndale Avenue 203744903 35 mph North McLean Boulevard Enter a location or zero to quit: 204000748 Location 204000748 has edges leading to: 761690915 35 mph University Street 424696634 35 mph University Street Enter a location or zero to quit: 203804462 Location 203804462 has edges leading to: 1782962464 25 mph North Evergreen Street 203848835 25 mph North Evergreen Street 203659689 25 mph Forrest Avenue 203804459 25 mph Forrest Avenue Enter a location or zero to quit: 203821515 Location 203821515 has edges leading to: 203874118 35 mph University Street 2471207719 35 mph University Street 203785186 25 mph Snowden Avenue Enter a location or zero to quit: 203744908 Location 203744908 has edges leading to: 203744906 35 mph North McLean Boulevard 203690459 45 mph Jackson Avenue 203670571 35 mph North McLean Boulevard 203761725 45 mph Jackson Avenue Enter a location or zero to quit: 203744906 Location 203744906 has edges leading to: 203659729 25 mph Crump Avenue 203744904 35 mph North McLean Boulevard 203744908 35 mph North McLean Boulevard Enter a location or zero to quit: 0
For the graph itself I made a class, but the important structures were (1) a map from IDs to locations, and (2) a map from IDs to the collection of roads that intersect the location corresponding to that ID. The collection of roads I stored as a vector. So I ended up with two structures that do most of the heavy lifting in this program:
map<long long, location> locations; map<long long, vector<road> > roads;
Vector: [ documentation 1 ] [ documentation 2 ] [ tutorial ]
Map: [ documentation 1 ] [ documentation 2 ] [ tutorial ]
vector<string> split(const string &s, char delim) { stringstream ss(s); // this requires #include <sstream> string item; vector<string> elems; while (getline(ss, item, delim)) { elems.push_back(item); } return elems; }