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
|
//Digraph Class Template
#include <list>
#include <vector>
#include <queue>
#include <iostream>
#include <fstream>
#include <iomanip>
#include <string>
using namespace std;
template <typename DataType>
class Digraph
{
//operation
public:
DataType Data(int k) const; //number k of vertex,data value stored in vertex #k
void Read(ifstream & inFile); //input operator
void Print(ostream & out); //output operator
void DepthFirstSearchAux(int start, vector <bool> & unvisited); //depth firstof diagraph, starting at vertex start.
void DepthFirstSearch(int start);
//find a shortest path in the diagraph from vertex start to vertex destination
vector<int> ShortestPath(int start, int destination);
private:
//head nodes of adjacency list
class VertexInfo
{
public:
DataType data;
list<int> adjacencyList;
};
//data members
vector<VertexInfo> v;
};
//definition of Data()
template <typename DataType>
inline DataType Digraph<DataType>::Data(int k) const
{
return v[k].data;
}
//definition of Read()
template <typename DataType>
void Digraph<DataType>::Read(ifstream & inFile)
{
VertexInfo vi; //VertexInfo vi;
int n, //number of vertices adjacent to some vertex
vertex; //the nuber of vertex
v.push_back(vi); //garbage 0-th value so indices start with 1,as it customary
for(;;)
{
inFile>>vi.data;
if(inFile.eof()) break;
inFile>>n;
list<int> adjList; //construct empty list
for (int i =1; i <=n; i++)
{
inFile>>vertex;
adjList.push_back(vertex);
}
vi.adjacencyList=adjList;
v.push_back(vi);
}
}
template <typename DataType>
void Digraph<DataType>::Print(ostream & out)
{
out<<"Adjacency-List Representation: \n";
for (int i=1; i < v.size(); i++)
{
out<<i<<":"<< v[i].data<<"--";
for(list<int>::iterator it = v[i].adjacencyList.begin();
it != v[i].adjacencyList.end(); it++)
out<<*it<<" ";
out<<endl;
}
}
//definition of DepthFirstSearch() and DepthFirstSearchAux()
template <typename DataType>
void Digraph<DataType>
::DepthFirstSearchAux(int start, vector<bool> & unvisited)
{
//add statement here to process v[start].data
cout<<v[start].data<<endl;
unvisited[start] = false;
//traverse its adjacency list,performing depth-first searches from each unvisited vertex in it.
for (list<int>::iterator
it = v[start].adjacencyList.begin();
it != v[start].adjacencyList.end(); it++)
//check if current vertex has been visited
if (unvisited[*it])
//start DFS from new node
DepthFirstSearchAux(*it, unvisited);
}
template <typename DataType>
void Digraph<DataType>::DepthFirstSearch(int start)
{
vector<bool> unvisited(v.size(), true);
DepthFirstSearchAux(start, unvisited);
}
//definition of ShortestPath()
template<typename DataType>
vector<int> Digraph<DataType>::ShortestPath(int start, int destination)
{
int n = v.size(); //number of vertices (#ed from 1)
vector<int> distLabel(n, -1), //distance labels for vertices, all marked as unvisited (-1)
predLabel(n); //predecessor labels for vertices
//perform breadth first search from Start to find destination,
//labeling vertices with distance from start as we go.
distLabel[start] = 0;
int distance = 0,
vertex;
queue<int> vertexQueue;
vertexQueue.push(start);
while (distLabel[destination] < 0 && !vertexQueue.empty())
{
vertex = vertexQueue.front();
vertexQueue.pop();
if (distLabel[vertex] > distance)
distance ++;
for (list<int>::iterator it = v[vertex].adjacencyList.begin();
it != v[vertex].adjacencyList.end(); it++)
if (distLabel[*it]<0)
{
distLabel[*it] = distance+1;
predLabel[*it] = vertex;
vertexQueue.push(*it);
}
}
distance++;
//now reconstruct the shortest path if there is one
vector<int> path(distance+1);
if(distLabel[destination]< 0)
cout<< "Destination not reachable from start vertex\n";
else
{
path[distance] = destination;
for (int k = distance-1; k >= 0; k--)
path[k] = predLabel[path[k+1]];
}
return path;
}
//The program
int main()
{
cout<<"Enter network file: ";
string networkFile;
cin>>networkFile;
ifstream inFile(networkFile.data());
if (!inFile.is_open())
{
cerr << "***Cannot Open file " << networkFile<<" ***\n";
exit(-1);
}
Digraph<string> d;
d.Read(inFile);
cout<<"The Digraph's " ;
d.Print (cout);
cout << endl;
int start, destination;
char response;
do
{
cout<<"Number of Start node? ";
cin>>start;
cout<<"Number of destination node? ";
cin>>destination;
vector<int> path = d.ShortestPath(start,destination);
cout<<"Shortest path is: \n";
for (int k=0; k<path.size(); k++)
{
cout<<setw(3)<<path[k]<<' '<<d.Data(path[k])<<endl;
cout<<" |\n"
" V\n";
}
cout<<setw(3)<<destination<<' '
<<d.Data(destination)<<endl;
cout<<"More (Y or N)? ";
cin>> response;
}
while (response == 'y' || response == 'Y');
}
|