man of La Mancha

to try when my arms are too weary

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::

 

  1 View Code 
  2 
  3 /*
  4     输入的文本中弧的起点,终点是按字典顺序排列的,所以算法对此作了相应简化
  5     即使不是按照字典顺序,也可以轻易的排列成字典顺序,这里不作考虑
  6     d:\mydir\1.txt网络地址:http://202.113.29.10/class/ds12/hw12p.txt 记录顶点信息
  7     d:\mydir\2.txt网络地址:http://202.113.29.10/class/ds12/hw12r.txt 记录弧信息
  8 */
  9 #include<iostream>
 10 #include<fstream>
 11 #include<vector>
 12 #include<queue>    //FIFO,不提供迭代器和下标访问
 13 #include<string>
 14 #include<iomanip>
 15 using namespace std;
 16 
 17 struct vertex
 18 {
 19     int num;
 20     double x,y;
 21 };
 22 struct arc
 23 {
 24     int head,tail;
 25     double length;
 26 };
 27 struct adjacency_matrix
 28 {
 29     bool status;        //邻接标志,邻接为true,不邻接为false
 30     int posi;            //元素对应的弧在arc类中的a对象中的位置
 31     double length;        //相邻两点间距,不相邻则为-1
 32     double shortest;    //两点间最短路径,用100000表示infinite
 33     vector<int> path;    //记录最短路径经过的顶点
 34 };
 35 inline bool min(double &a,double b)
 36 {
 37     if(a>b)
 38         {a=b;return true;}
 39     else
 40         return false;
 41 };
 42 class graph
 43 {
 44 private:
 45     vector<vertex> v;
 46     vector<arc> a;
 47     vector<adjacency_matrix> am;    
 48     int vertex_num;
 49     int arc_num;
 50 public:
 51     graph();
 52     int pos(int a,int b);
 53     void Reduct();
 54     void Dijkstra(int init);
 55     void Dijkstra_Shortest_Distance();
 56     void Floyd_Shortest_Distance();
 57     void Dijkstra_Print();
 58     void Floyd_Print();
 59 };
 60 graph::graph()
 61 {
 62     int i,j,pos;
 63     double x,y;
 64     string s;
 65     vertex temp;
 66     arc buf;
 67     adjacency_matrix store;
 68 //--读入点信息:下标0的元素无意义,下标1-vertex_num的元素顺序记录点信息--
 69     fstream point("d:\\mydir\\1.txt");
 70     if(point.fail())
 71         {cerr<<"open failed!"<<endl;return;}
 72     getline(point,s,'\n');
 73     temp.num=0;temp.x=temp.y=0;
 74     v.push_back(temp);
 75     while(!point.eof())
 76         {
 77             point>>temp.num>>temp.x>>temp.y;
 78             v.push_back(temp);
 79         }
 80     vertex_num=v.size()-1;
 81     point.close();
 82 //--读入弧信息:下标0的元素无意义,下标1-arc_num的元素顺序记录弧信息--
 83     fstream line("d:\\mydir\\2.txt");
 84     if(line.fail())
 85         {cerr<<"open failed!"<<endl;return;}
 86     getline(line,s,'\n');
 87     buf.head=buf.tail=0;buf.length=0;
 88     a.push_back(buf);
 89     while(!line.eof())
 90         {
 91             line>>buf.head>>buf.tail;
 92             x=v[buf.head].x-v[buf.tail].x;
 93             y=v[buf.head].y-v[buf.tail].y;
 94             buf.length=sqrt(x*x+y*y);
 95             a.push_back(buf);
 96         }
 97     arc_num=a.size()-1;
 98     line.close();
 99 //--创建邻接矩阵:下标0的元素无意义,下标1-vertex_num*vertex_num的元素顺序记录相邻信息--
100     //------初始邻接矩阵,最短路径设置为100000,任意两点间距为-1----------------------
101     store.status=false;store.posi=-1;store.length=-1;store.shortest=100000;store.path.push_back(0);
102     am.push_back(store);
103     for(i=1;i<=vertex_num;++i)
104         for(j=1;j<=vertex_num;++j)
105             {
106                 store.path.clear();
107                 store.path.push_back(i);store.path.push_back(j);
108                 am.push_back(store);
109             }
110     //------依据弧信息改写邻接矩阵,将相邻点的最短路径暂时设定为两点间距----------------
111     for(i=1;i<=arc_num;++i)
112         {
113             //------给邻接矩阵赋值-------------------
114             pos=(a[i].head-1)*vertex_num+a[i].tail;
115             am[pos].status=true;am[pos].posi=i;am[pos].length=am[pos].shortest=a[i].length;
116         }
117     //------顶点自身到自身的最短距离设定为0------
118     for(i=1;i<=vertex_num;++i)
119         am[(i-1)*vertex_num+i].shortest=0;
120 //--测试读入结果--
121     //--将读入的信息存储到d:\mydir\read_text.txt中--------------------
122     fstream read_test;
123     read_test.open("d:\\mydir\\read_test.txt",ios::out|ios::trunc);
124     if(read_test.fail())
125         {
126             cerr<<"read_test.txt open failed ! "<<endl;
127             system("pause");
128         }
129     //--测试点信息--
130     read_test<<"the number of vertex:"<<vertex_num<<endl;
131     for(i=1;i<=vertex_num;++i)
132         {
133             read_test<<setiosflags(ios::left);
134             read_test<<setw(4)<<v[i].num<<setw(4)<<v[i].x<<setw(4)<<v[i].y<<endl;
135         }
136     //--测试弧信息--
137     read_test<<"the number of arc:"<<arc_num<<endl;
138     for(i=1;i<=arc_num;++i)
139         {
140             read_test<<setiosflags(ios::left);
141             read_test<<setw(4)<<a[i].head<<setw(4)<<a[i].tail;
142             read_test<<setw(10)<<a[i].length<<endl;
143         }
144     //--测试邻接矩阵信息--
145     read_test<<"the adjacency matrix:"<<endl;
146     for(i=1;i<=vertex_num*vertex_num;++i)
147         {
148             if(am[i].status==false)
149                 read_test<<"F ";
150             else
151                 {
152                     read_test<<"T ";
153                     read_test<<setiosflags(ios::left);
154                     read_test<<setw(4)<<am[i].posi;
155                     read_test<<setw(4)<<a[am[i].posi].head<<setw(4)<<a[am[i].posi].tail;
156                     read_test<<am[i].length<<endl;
157                 }
158             if(i%vertex_num==0)
159                 read_test<<endl;
160         }
161 }
162 int graph::pos(int a,int b)
163 {
164     return (a-1)*vertex_num+b;
165 }
166 //--Reduct函数:还原邻接矩阵到初始化状态--
167 void graph::Reduct()
168 {
169     int i,j,k,temp;
170     for(i=1;i<=vertex_num;++i)
171         for(j=1;j<=vertex_num;++j)
172             {
173                 k=pos(i,j);
174                 am[k].status=false;am[k].shortest=100000;
175                 am[k].path.clear();am[k].path.push_back(i);am[k].path.push_back(j);
176             }
177     //------依据弧信息改写邻接矩阵,将相邻点的最短路径暂时设定为两点间距----------------
178     for(i=1;i<=arc_num;++i)
179         {
180             //------给邻接矩阵赋值-------------------
181             temp=(a[i].head-1)*vertex_num+a[i].tail;
182             am[temp].status=true;am[temp].posi=i;am[temp].length=am[temp].shortest=a[i].length;
183         }
184     //------顶点自身到自身的最短距离设定为0------
185     for(i=1;i<=vertex_num;++i)
186         am[(i-1)*vertex_num+i].shortest=0;
187 };
188 //--Dijkstra函数:用Dijkstra算法返回第init个点到其他所有点的最小路径--
189 void graph::Dijkstra(int i)
190 {
191 //--初始化--
192     //--l为loop缩写,是循环变量,对应邻接矩阵am--
193     //--i=init记录源点;j记录正在计算的终点;k为路上经过的点--
194     //--q对应"已经读取"集合S,初始化只含一个元素init--
195     //--b_push,b_pop分别对应顶点压入过队列和推出过队列,初始化为false--
196     bool b;
197     int j,k,l;
198     queue<int> q;
199     vector<bool> b_push,b_pop;
200     q.push(i);
201     for(l=0;l<=vertex_num;++l)
202         {
203             b_push.push_back(false);
204             b_pop.push_back(false);
205         }
206     b_push[i]=true;
207 //--求最短路径--
208     //--当队列非空时,从队列的头部推出一个顶点init-----------------------------------
209     //--查找与init相邻且未压入过队列的顶点,使之入队列--------------------------------
210     //--查找与init相邻且未被推出队列的顶点,通过比较重定义它们的最短距离-----------------
211     while(!q.empty())
212         {
213             //--推出队列头部的一个顶点,并在b_pop中标记--
214             k=q.front();q.pop();b_pop[k]=true;
215             for(l=pos(k,1);l<=pos(k+1,0);++l)
216                 {
217                     j=l-(k-1)*vertex_num;
218                 //--查找与之相邻且未压入过队列的顶点,将它们压入队列--
219                     if(am[l].status==true&&b_push[j]==false)
220                         {
221                             //--压入队列,并在b_push中标记-----
222                             q.push(j);b_push[j]=true;
223                         }
224                 //--查找与之相邻且未推出过队列的顶点,并按下列算法重定义最短距离,同时重定义最短路径--
225                     //--distance[i][j] = min ( distance[i][j], distance[i][k]+distance[k][j] )--
226                     if(am[l].status==true&&b_pop[j]==false)
227                         {
228                             b=min(am[pos(i,j)].shortest,am[pos(i,k)].shortest+am[pos(k,j)].shortest);
229                             if(b==true)
230                                 {
231                                     am[pos(i,j)].path.clear();
232                                     for(unsigned m=0;m<am[pos(i,k)].path.size();++m)
233                                         am[pos(i,j)].path.push_back(am[pos(i,k)].path[m]);
234                                     am[pos(i,j)].path.push_back(j);
235                                 }
236                         }
237                 }
238         }
239     /*
240 //--测试Dijkstra算法的结果---------
241     for(l=0;l<vertex_num;++l)
242         {
243             cout<<" ("<<i<<","<<l<<") "<<am[pos(i,l)].shortest<<"  ";
244             if((i+1)%5==0)
245                 cout<<endl;
246         }
247     */
248 };
249 //--起点、终点、最短距离、中间依次经过的路口编号--
250 void graph::Dijkstra_Shortest_Distance()
251 {
252     for(int i=1;i<=vertex_num;++i)
253         Dijkstra(i);
254 }
255 //--Floyd_Shortest_Distance函数:用Floyd算法返回所有点之间的最小路径--
256 void graph::Floyd_Shortest_Distance()
257 {
258     bool b;
259     unsigned l;
260     int i,j,k;
261     for(k=1;k<=vertex_num;++k)
262         for(i=1;i<=vertex_num;++i)
263             for(j=1;j<=vertex_num;++j)
264                 {
265                 //--用以下算法分别对最短距离和路径赋值----------
266                     //--if(dist[i][k]+dist[k][j]<dist[i][j])
267                             //--dist[i][j]=dist[i][k]+dist[k][j];
268                             //--path[i][j]=path[i][k]+path[k][j];
269                     b=min(am[pos(i,j)].shortest,am[pos(i,k)].shortest+am[pos(k,j)].shortest);
270                     if(b==true)
271                         {
272                             am[pos(i,j)].path.clear();
273                             for(l=0;l<am[pos(i,k)].path.size()-1;++l)
274                                 am[pos(i,j)].path.push_back(am[pos(i,k)].path[l]);
275                             for(l=0;l<am[pos(k,j)].path.size();++l)
276                                 am[pos(i,j)].path.push_back(am[pos(k,j)].path[l]);
277                         }
278                 }
279 };
280 void graph::Dijkstra_Print()
281 {
282     //--创建文件,文件名为:Dijkstra_shortest_distance.txt,位置D盘-----
283     fstream shortest_distance;
284     shortest_distance.open("d:\\mydir\\Dijkstra_shortest_distance_and_path.txt",ios::out|ios::trunc);
285     if(shortest_distance.fail())
286         {cerr<<"Dijkstra open failed!"<<endl;system("pause");}
287     //--用插入器 << 将数据写入文件---
288     for(int i=1;i<=vertex_num;++i)
289         {    
290             for(int j=1;j<=vertex_num;++j)
291                 {
292                     shortest_distance<<setiosflags(ios::left);
293                     shortest_distance<<" ("<<setw(3)<<i<<","<<setw(3)<<j<<") ";
294                     if(am[pos(i,j)].shortest!=100000)
295                         {
296                             shortest_distance<<setw(10)<<am[pos(i,j)].shortest<<" ";
297                             for(int k=0;k!=am[pos(i,j)].path.size();++k)
298                                 shortest_distance<<setw(3)<<am[pos(i,j)].path[k]<<" ";
299                         }
300                     else
301                         {
302                             shortest_distance<<setw(11)<<"Infinite";
303                             shortest_distance<<"no path";
304                         }
305                     shortest_distance<<endl;
306                 }
307         }
308 }
309 void graph::Floyd_Print()
310 {
311     //--创建文件,文件名为:Floyd_shortest_distance.txt,位置D盘-----
312     fstream shortest_distance;
313     shortest_distance.open("d:\\mydir\\Floyd_shortest_distance_and_path.txt",ios::out|ios::trunc);
314     if(shortest_distance.fail())
315         {cerr<<"Floyd open failed!"<<endl;system("pause");}
316     //--用插入器 << 将数据写入文件---
317     for(int i=1;i<=vertex_num;++i)
318         {    
319             for(int j=1;j<=vertex_num;++j)
320                 {
321                     shortest_distance<<setiosflags(ios::left);
322                     shortest_distance<<" ("<<setw(3)<<i<<","<<setw(3)<<j<<") ";
323                     if(am[pos(i,j)].shortest!=100000)
324                         {
325                             shortest_distance<<setw(10)<<am[pos(i,j)].shortest<<" ";
326                             for(int k=0;k!=am[pos(i,j)].path.size();++k)
327                                 shortest_distance<<setw(3)<<am[pos(i,j)].path[k]<<" ";
328                         }
329                     else
330                         {
331                             shortest_distance<<setw(11)<<"Infinite";
332                             shortest_distance<<"no path";
333                         }
334                     shortest_distance<<endl;
335                 }
336         }
337 };
338 int main()
339 {
340     graph g;
341     g.Dijkstra_Shortest_Distance();
342     g.Dijkstra_Print();
343     g.Reduct();
344     g.Floyd_Shortest_Distance();
345     g.Floyd_Print();
346     system("pause");
347     return 0;
348 }

 

 

参考资料:

    Dijkstra算法为单源点最短路径算法:   图文示例:http://zh.wikipedia.org/zh-cn/Dijkstra%E7%AE%97%E6%B3%95

                        编程实例:http://www.nocow.cn/index.php/Dijkstra%E7%AE%97%E6%B3%95

    Floyd算法为全源点最短路径算法:     图文示例:http://www.cnblogs.com/pelephone/articles/floyd-algorithm.html

                          编程实例:http://www.cnblogs.com/hackerain/archive/2010/12/05/2130431.html

 

2012-06-03

posted on 2012-06-03 10:01  黄金后裔  阅读(270)  评论(0编辑  收藏  举报