Steps to the Shortest Path

Army of Ants method

  1. Create a struct to represent a city. Perhaps just name, longitude, latitude, population; it is easy to add more later when needed.

  2. Create an array of pointers to city objects. An array is NOT really good enough, but if you program modularly, if you use an even slightly object oriented approach, it will be easy to replace the array with a Vector, A FlexArray, or a Linked List at some point in the future. Let's just get it working.

  3. Read the data file into the array, and make sure it has been read correctly. A good test is to enter an interactive loop: you type a city name, and it finds the city and reports ann known information about it.

  4. Design a struct to represent a road, containing a string for name, number for length, and city* pointers for each of the citirs it connects. Don't bother to make an array for all the roads.

  5. Read the roads data. As you read each road record, look up the names of the cities that it connects (in the already-existing-and-tested array of cities). Create a proper road* object containing the appropriate city* values. Test it. For every road that you read from the file, print all of its data plus all of the data for the two cities that it connects. Now you know that it is working properly.

  6. Add to your city struct a short array of road *'s. An array really really isn't good enough, but again, let's get it working, then replace the works with something better. That is what modular deisgn is all about.

  7. Modify your road reader: for every record that it reads from the file, it should create two copies of the road object, identical in every way except that the two city* values are swapped around. The two copies of the road object are added to the array of roads for each of the cities that they connect.

    So now every city in your big array contains a name, position, population, and array of (pointers to) road objects. Each of those road objects contains a name, length, and two pointers to city objects.

  8. Test the program so far with some user controlled exploration: The program always remembers the "current city" while executing a simple loop. At each stage:

    1. Print the current city's name and details.
    2. Print the list of all roads leading from that city.
    3. Let the user select one of those roads (perhaps just entering a number: 3 means the 3rd road in the list).
    4. Follow that road, seeting "current city" to whatever city is at the other end of it.
    5. Repeat, until you are sure everything is perfect.

    Make sure you can accurately navigate throughout the world this way.

  9. Ask the user where their starting point is. Create a heap containing just that one city. It is a very small heap, but will soon grow. A heap with just one entry requires no effort to create. Cities will be added to and removed from this heap as the shortest path algorithm progresses. Heaps require that their contents have some indication of their importance or priority. Add to the city struct a number, the ETA for the army of ants arriving at that city. The ETA member of a city is the priority value used to order the heap.

  10. The Big Main Loop
    1. Remove from the heap the city that has the lowest (highest priority) ETA. If the heap is empty, the loop stops. Remember to repair the heap after removing the first city. The removed city becomes the "current city".
    2. Set the global "time now" variable to that city's ETA. Your army of ants has just arrived at the seletcted city, and that is the time.
    3. Look at every road leading from the current city. There are N roads leading out of it. "C0" represents the current city. "T0" is the time now (ETA for that C0). "N" is the number of roads leading out of it. "Ri" is the length of the ith road. "Di" is the city at the other end of the ith road. For each i in 0...N-1:
      1. Compute a new ETA for the city at the other end of the ith road: Ti = T0 + Ri.
      2. If Ti is greater than or equal to the ETA already recorded for that city, then ignore it. We already know a shorter way to get there, this road adds nothing useful.
      3. If The other city is not already in the heap, add it. Its priority is the ETA, Ti, just computed. Make sure you do a proper heap addition, so the new city finds its correct position in the heap.
      4. If the other city is already in the heap, but the ETA previously worked out for it is greater than the new one, Ti, then change its ETA to Ti, and correct the heap. The adjusted city may have to move closer to the top of the heap.
      5. Repeat for each of the N roads leading from C0.
      Note for the previous steps: How do you know whether city X is already in the heap? Easy: add to each city struct a "where" member. "Where" is initially 0, indicating "not in the heap". Whenever a city is added to the heap, its "where" is set to its position in the heap. Whenever a city's position in the heap is adjusted, its "where" is also adjusted. Thus, you can always find whether and where a city is already in the heap without any kind of searching.

  11. Make sure it worked.
    The Big Main Loop contnues until the heap is empty. After the loop becomes empty, enter another very siple loop. This one just runs through the entire array of cities, printing for each its name and ETA. Of course, all those printed ETAs are now in the past, but if you look at the map, you will see that what was printed is actually the lengths of the shortest paths from the starting city to every toher city. Check that the results are correct.

  12. Now ask the user what the destination city was. You have already worked out how far it is from the start point, before you ever knew what it was. By working backwards, you can easily find the sequence of roads that constitute the shortest path.
    For example, if you know the shortest path from Amman to Zanzibar is 100 miles long, and there are only three roads leading into Zanzibar, you want to know which of those three is actually part of the 100-mile long shortest path. Let's say that the three roads leading in to Z are Interstate 17 (which is 40 miles long, and connects to Kalamazoo), the Via Apia (25 miles long, leading to Rome), and the B-4393 (3 miles long, leading to Llaneyllin). Which is the right one? Look at the shortest distances (old ETAs) for the cities: If I-17 is the correct road, the shortest path from Amman to Kalamazoo must be 100-40 = 60 miles. If the Apian Way is correct, then the shortest distance from Amman to Rome must be 100-25 = 75 miles. If the B-4393 is the right way, then the shortest distance from Amman to Llaneyllin must be 100-3 = 97 miles. One of those must be the already-caulculated shortest distance to the appropriate city, that tells you which road to take. In this way, it is easy to work all the way back to Amman, and print the whole list of roads.

  13. Draw the picture. Make the results look good. At least print out the route in a clear, user-friendly manner.

  14. Now remember to go back and change your arrays to nice efficient structures.