图-指尖上的舞蹈

·背景

在大部分数据结构的讲义中,图一般出现在第7章。可惜当年没好好学,现在重新拿出来啃一遍。印象中不少老师对于该章节都填鸭式的带过或者摆在最后开讲,也许因为当年LBS并不流行。在其章节后的是一些排序和管理,但就概念复杂度或者封装流行度而言,图还是更难一点。如果仅靠伪代码,需要更长的时间来消化。图,也许就像游戏中的最终BOSS一样,其恐惧、神秘、优雅、传说还是吸引着众多Fans们趋之若鹜。这两天边回忆、边吃饭、边吐血、边洗澡把最常用的一些观点重新笔记下来,但其实也只是冰山一角。

·分解

    历经百年,图的构成和运用已经遍布生活,其中欧洲人对于这块的贡献最大。整个图衍生出多个发展方向,如下图所示:

 图-指尖上的舞蹈_第1张图片

底层的图是一个大概念,如果没什么特别需求,可以理解就是我们的地图,只不过它更原始一点,更苍白一点,就一些线和点。

往上一层,分解出了有向、无向。也就是有没有箭头的区别,单行道、双行道的区别。

往上一层,分解出了权值。也就是这条路好不好走,要花多大代价走这条路。

往上一层,分解出了基于图应用算法。有一些基本的算法其实是通用的,笔者就目前流行的趋势稍微归一下类。

·基本遍历:DFS、BFS。一个按前序遍历,一个按层序遍历。帮助入门,缺点上:凡是遍历过的不再触碰,容易导致变形数。

·最小生成树:Prim、Kruskal。经常会听搞网络的同学说起,当然听到这个词语的时候,但后面两个名词很少听到,其实就是它们。一般来说,听到时候,多数是有人插错网线成环了。

·最短路径:Dijkstra。名字很难念,很多应用的看家法宝。其他还有一些算法就不举例了。缺点上,一般只给了结果,要想知道过程(路由明细),还需要再加工。

·强连通:Tarjen。一个找强连通的分量的算法,两两互联称为强连通。但具体能干什么用,还没想通,分类?机学?后续待研究。

·图匹配:匈牙利算法:二分图的最大匹配常用算法,同上,后续待研究。

 

·前三项算法的举例

原理就不多写了,网上都有,这里就边贴代码边分析。

·DFS:

图-指尖上的舞蹈_第2张图片图-指尖上的舞蹈_第3张图片       图-指尖上的舞蹈_第4张图片

 

  1 #include <iostream>
  2 #include <sstream>
  3 #include <fstream>
  4 #include <stdlib.h>
  5 #include <string.h>
  6 #include <vector>
  7 #include <typeinfo>
  8 #include <set>
  9 #include <stack>
 10 
 11 
 12 using namespace std;
 13 
 14 typedef string VertexType;                //顶点类型应由用户定义
 15 typedef int EdgeType;                   //边上的权值类型应由用户定义
 16 typedef int Boolean;
 17  
 18                                //最大顶点数,应由用户定义
 19 #define INF  -1       //用-1来代表无穷大
 20 #define DEBUG
 21 #define TRUE 1
 22 #define FALSE 0
 23 
 24 
 25 typedef struct
 26 {
 27    VertexType vexs[5];            //顶点表
 28    EdgeType   arc[5][5];     //邻接矩阵,可看作边
 29    int numVertexes, numEdges;          //图中当前的顶点数和边数
 30 } Graph;
 31 
 32 typedef struct
 33 {
 34   char d1[2];
 35   char d2[2];
 36   int    wv;
 37 } Wing;
 38 
 39 typedef struct
 40 {
 41   vector<string> v1;
 42   vector<string> v2;
 43   vector<int>    v3;
 44 } Route;
 45 
 46 Boolean visited[5];        //访问标志数组
 47 Route *r;                  //路由表
 48 int rp=0;                  //路由表长度
 49 stack<string> minroute;    //最短路径栈
 50 
 51 
 52 int locates(Graph *g, string sch);
 53 void init(Graph *g);
 54 void printGraph(Graph g);
 55 void CreateGraph(Graph *g,Wing *ww,vector<string> &v);
 56 void DFS(Graph g, int i,vector<string> &v);
 57 void DFSclear(Graph g,vector<string> &v);
 58 void DFSR(Graph g, int i, vector<string> &v,Route *r,stack<string> &stk);
 59 
 60 
 61 int main()
 62 {
 63    //放原始图
 64    Wing *w=NULL;
 65    w=(Wing*)malloc(sizeof(Wing)*6);
 66 
 67 
 68    //读原始图
 69    std::ios::sync_with_stdio(false);
 70    string line;
 71    string filename="./tu004.cfg";
 72    ifstream ifs;
 73    ifs.open(filename.c_str());
 74    int i=0;
 75    set<string> v2;
 76    vector<string> v1;  //遍历线序
 77    while(getline(ifs,line))
 78    {
 79           istringstream strstm(line);
 80           string str1,str2,str3;
 81           strstm>>str1>>str2>>str3;
 82           strcpy((w+i)->d1,str1.c_str());
 83           strcpy((w+i)->d2,str2.c_str());
 84           (w+i)->wv=atoi(str3.c_str());
 85           v2.insert(str1);
 86           v2.insert(str2);
 87           i++;
 88    }
 89 
 90    //邻接矩阵创建图和顶点数组枚举创建
 91    Graph g;
 92    
 93    set<string>::iterator v2_it;
 94    for(v2_it=v2.begin();v2_it!=v2.end();v2_it++)
 95    {
 96          v1.push_back(*v2_it);
 97    }
 98 
 99    //设置顶点和边上限
100    g.numVertexes=5;
101    g.numEdges=6;
102    
103    //开始干活
104    init(&g);
105    CreateGraph(&g,w,v1);
106    printGraph(g);
107 
108    //结束
109    free(w);
110 
111    //DFS 深度优先全遍历
112    /*
113    for(int i=0;i<5;i++)
114    {
115                 DFSclear(g,v1);
116                 DFS(g,i,v1);
117                 for(int j=0;j<5;j++)
118                         cout<<v1[j]<<" ";
119                 cout<<"---------------------------------------------------------------------"<<endl;
120 
121    }
122    */
123 
124    //DFS 深度优先,输出路由表
125    r=(Route*)malloc(sizeof(Route)*6);
126    DFSclear(g,v1);
127    DFSR(g,2,v1,r,minroute);
128    for(int j=0;j<5;j++)
129       cout<<v1[j]<<" ";
130    cout<<"\n---------------------------------------------------------------------"<<endl;
131 
132    //打印路由表
133    for(int j=0;j<rp;j++)
134            cout<<r->v1[j]<<":"<<r->v2[j]<<":"<<r->v3[j]<<endl;
135 
136    cout<<"\n---------------------------------------------------------------------"<<endl;
137 
138    //打印最短路径
139     while(minroute.size()>0)
140     { 
141                 cout<<minroute.top()<<endl;
142                 minroute.pop();
143         }
144 }
145 
146 
147 void DFSR(Graph g, int i, vector<string> &v,Route *r, stack<string> &stk)
148 {
149    cout<<"进入遍历中"<<i<<":";
150    stk.push(g.vexs[i]);
151    v.push_back(g.vexs[i]);
152    int j;
153    visited[i] = TRUE;
154    cout<<" 顶点:"<<g.vexs[i]<<endl;
155    for(j = 0; j < g.numVertexes; j++)
156    {
157        cout<<"\t遍历点:"<<j<<"的状态"<<visited[j]<<" "<<"g.arc的值"<<g.arc[i][j]<<endl;
158        if(g.arc[i][j] == 1 && !visited[j])
159        {
160            cout<<"\t\t\t\t   准备进入下一点:"<<j<<endl;
161            cout<<"\t\t\t\t\t\t "<<i<<":"<<j<<":"<<g.arc[i][j]<<endl;
162                    r->v1.push_back(g.vexs[i]);
163                    r->v2.push_back(g.vexs[j]);
164                    r->v3.push_back(g.arc[i][j]);
165                    rp++;
166            DFSR(g,j,v,r,stk);                  //对为访问的邻接顶点递归调用
167        }
168     }
169     if(stk.top()=="3")
170         {
171       cout<<"完成最短路径"<<endl;
172         }
173         else
174         {
175                 stk.pop();
176         }
177     cout<<"结束本次"<<i<<"遍历"<<endl;
178 }
179 
180 
181 
182 void DFS(Graph g, int i, vector<string> &v)
183 {
184    cout<<"进入遍历中"<<i<<":";
185    v.push_back(g.vexs[i]);
186    int j;
187    visited[i] = TRUE;
188    cout<<" 顶点:"<<g.vexs[i]<<endl;
189    //printf("%s ", g.vexs[i].c_str());                           //打印顶点,也可以其他操作
190    for(j = 0; j < g.numVertexes; j++)
191    {
192            cout<<"\t遍历点:"<<j<<"的状态"<<visited[j]<<" "<<"g.arc的值"<<g.arc[i][j]<<endl;
193        if(g.arc[i][j] == 1 && !visited[j])
194        {
195                   cout<<"\t\t\t\t   准备进入下一点:"<<j<<endl;
196                   cout<<"\t\t\t\t\t\t "<<i<<":"<<j<<":"<<g.arc[i][j]<<endl;
197           DFS(g,j,v);                  //对为访问的邻接顶点递归调用
198        }
199    }
200    cout<<"结束本次"<<i<<"遍历"<<endl;
201 }
202 
203 
204 
205 
206 
207 void DFSclear(Graph g,vector<string> &v)
208 {
209     int i;
210         cout<<endl;
211         cout<<"初始化所有顶点状态都是未访问过状态"<<endl;
212     for(i = 0; i < g.numVertexes; i++)
213     {
214        visited[i] = FALSE;         //初始化所有顶点状态都是未访问过状态
215     }
216         v.clear();
217 }
218 
219 
220 
221 
222 void CreateGraph(Graph *g,Wing *ww,vector<string> &v)
223 {
224         printf("刚才输入顶点数和边数为:%d %d\n", g->numVertexes, g->numEdges);
225     //设置顶点数组
226         for(int i=0;i<g->numVertexes;i++)
227         {
228                  g->vexs[i]=v[i];
229                  cout<<g->vexs[i]<<" ";
230                  //printf("%s ",g->vexs[i].c_str());
231         }     
232         cout<<endl;
233 
234 
235         //矩阵赋值
236         for(int k=0;k<6;k++)
237         {
238                 int m=-1;
239                 int n=-1;
240                 m = locates(g,(ww+k)->d1);
241                 n = locates(g,(ww+k)->d2);
242 
243         if(n == -1 || m == -1)
244             {
245                fprintf(stderr, "there is no this vertex.\n");
246                return;
247             }
248             //printf("m=%d,n=%d\n",m,n);
249             g->arc[m][n] = (ww+k)->wv;
250             g->arc[n][m] = g->arc[m][n]; 
251         }
252 
253 }
254 
255 void init(Graph *g)
256 {
257         for(int i=0;i<g->numVertexes;i++)
258                 for(int j=0;j<g->numVertexes;j++)
259                 {
260                   g->arc[i][j]=0;
261                 }
262 }
263 
264 
265 
266 int locates(Graph *g,string sch)
267 {
268    int i = 0;
269    for(i = 0; i < g->numVertexes; i++)
270    {
271      if(g->vexs[i] == sch)
272      {
273          break;
274      }
275    }
276    if(i >= g->numVertexes)
277    {
278         return -1;
279     }
280    return i;
281 }
282 
283 void printGraph(Graph g)
284 {
285   printf("开始打印\n");
286   int i, j;
287   for(i = 0; i < g.numVertexes; i++)
288   {
289         for(j = 0; j < g.numVertexes; j++)
290         {
291           printf("%d  ", g.arc[i][j]);
292          }
293       printf("\n");
294   }
295 }
无向图

 结果:

图-指尖上的舞蹈_第5张图片

 =================================================================================

·Prim:

图-指尖上的舞蹈_第6张图片 图-指尖上的舞蹈_第7张图片      图-指尖上的舞蹈_第8张图片

 

原Prim算法中用的For遍历,我稍微改了一下,走嵌套,每个次只选择两个分支最为待选拓扑分支。

  1 #include <iostream>
  2 #include <sstream>
  3 #include <fstream>
  4 #include <stdlib.h>
  5 #include <string.h>
  6 #include <vector>
  7 #include <typeinfo>
  8 #include <set>
  9 #include <stack>
 10 #include <map>
 11 
 12 
 13 
 14 using namespace std;
 15 
 16 typedef string VertexType;                //顶点类型应由用户定义
 17 typedef int EdgeType;                   //边上的权值类型应由用户定义
 18 typedef int Boolean;
 19  
 20 #define DM 6           //顶点数
 21 #define WM 8           //边数
 22 #define INF  -1       //用-1来代表无穷大
 23 #define DEBUG
 24 #define TRUE 1
 25 #define FALSE 0
 26 
 27 
 28 typedef struct
 29 {
 30    VertexType vexs[DM];            //顶点表
 31    EdgeType   arc[DM][DM];     //邻接矩阵,可看作边
 32    int numVertexes, numEdges;          //图中当前的顶点数和边数
 33 } Graph;
 34 
 35 typedef struct
 36 {
 37   char d1[2];
 38   char d2[2];
 39   int    wv;
 40 } Wing;
 41 
 42 typedef struct
 43 {
 44   vector<string> v1;
 45   vector<string> v2;
 46   vector<int>    v3;
 47 } Route;
 48 
 49 Boolean visited[DM];        //访问标志数组
 50 Route *r;                  //路由表
 51 int rp=0;                  //路由表长度
 52 stack<string> mrs;    //最短路径栈
 53 
 54 
 55 int locates(Graph *g, string sch);
 56 void init(Graph *g);
 57 void printGraph(Graph g);
 58 void CreateGraph(Graph *g,Wing *ww,vector<string> &v);
 59 void DFS(Graph g, int i,vector<string> &v);
 60 void DFSclear(Graph g,vector<string> &v);
 61 void DFSR(Graph g, int i, vector<string> &v,Route *r,stack<string> &stk);
 62 void Prim(Graph g,int i);
 63 
 64 
 65 int main()
 66 {
 67    //放原始图
 68    Wing *w=NULL;
 69    w=(Wing*)malloc(sizeof(Wing)*8);
 70 
 71 
 72    //读原始图
 73    std::ios::sync_with_stdio(false);
 74    string line;
 75    string filename="./tu007.cfg";
 76    ifstream ifs;
 77    ifs.open(filename.c_str());
 78    int i=0;
 79    set<string> v2;
 80    vector<string> v1;  //遍历线序
 81    while(getline(ifs,line))
 82    {
 83           istringstream strstm(line);
 84           string str1,str2,str3;
 85           strstm>>str1>>str2>>str3;
 86           strcpy((w+i)->d1,str1.c_str());
 87           strcpy((w+i)->d2,str2.c_str());
 88           (w+i)->wv=atoi(str3.c_str());
 89           v2.insert(str1);
 90           v2.insert(str2);
 91           i++;
 92    }
 93 
 94    //邻接矩阵创建图和顶点数组枚举创建
 95    Graph g;
 96    
 97    set<string>::iterator v2_it;
 98    for(v2_it=v2.begin();v2_it!=v2.end();v2_it++)
 99    {
100          v1.push_back(*v2_it);
101    }
102 
103    //设置顶点和边上限
104    g.numVertexes=DM;
105    g.numEdges=WM;
106    
107    //开始干活
108    init(&g);
109    CreateGraph(&g,w,v1);
110    printGraph(g);
111 
112    //结束
113    free(w);
114 
115    //开始Prim算法
116    DFSclear(g,v1);
117    Prim(g,2);
118 }
119 
120 
121 void Prim(Graph g,int i)
122 {
123     cout<<"进入遍历中"<<i<<":"<<endl;     
124         visited[i] = TRUE;
125         int mn=999;
126         map<int,int> a;
127         for(int j = 0; j < g.numVertexes; j++)
128         {
129            cout<<visited[j]<<" ";
130            if(g.arc[i][j]>0 && !visited[j])
131        {
132              a[g.arc[i][j]]=j;     
133            }
134         }
135         map<int,int>::iterator a_it=a.begin();
136 
137         cout<<endl;
138         for(a_it;a_it!=a.end();a_it++)
139         {
140            cout<<"*权值列表="<<a_it->first<<" NEXT:"<<a_it->second<<endl;
141         }
142 
143         a_it=a.begin();
144 
145         cout<<"\t权值="<<a_it->first<<" NEXT:"<<a_it->second<<" MAP SIZE:"<<a.size()<<endl;
146 
147     if(a.size()>0)
148         {
149                 if(a_it->first>0 && !visited[a_it->second])
150                 {
151                         cout<<"\t进入下一步:"<<a_it->second<<endl;
152                         Prim(g,a_it->second);
153                 }
154                 a_it++;
155                 if(a_it->first>0 && !visited[a_it->second])
156                 {
157                         cout<<"\t进入下一步:"<<a_it->second<<endl;
158                          Prim(g,a_it->second);
159                 }
160         }
161 
162             cout<<"开始返回:"<<i<<endl;
163 }
164 
165 
166 void DFSR(Graph g, int i, vector<string> &v,Route *r, stack<string> &stk)
167 {
168    cout<<"进入遍历中"<<i<<":";
169    stk.push(g.vexs[i]);
170    v.push_back(g.vexs[i]);
171    int j;
172    visited[i] = TRUE;
173    cout<<" 顶点:"<<g.vexs[i]<<endl;
174    for(j = 0; j < g.numVertexes; j++)
175    {
176        cout<<"\t遍历点:"<<j<<"的状态"<<visited[j]<<" "<<"g.arc的值"<<g.arc[i][j]<<endl;
177        if(g.arc[i][j] == 1 && !visited[j])
178            //if(g.arc[i][j] == 1 )
179        {
180            cout<<"\t\t\t\t   准备进入下一点:"<<j<<endl;
181            cout<<"\t\t\t\t\t\t  "<<i<<":"<<j<<":"<<g.arc[i][j]<<endl;
182                    r->v1.push_back(g.vexs[i]);
183                    r->v2.push_back(g.vexs[j]);
184                    r->v3.push_back(g.arc[i][j]);
185                    rp++;
186            DFSR(g,j,v,r,stk);                  //对为访问的邻接顶点递归调用
187        }
188     }
189   
190     if(stk.top()=="5")
191         {
192       cout<<"完成最短路径"<<endl;
193         }
194         else
195         {
196                 stk.pop();
197         }
198     cout<<"结束本次"<<i<<"遍历"<<endl;
199     
200 }
201 
202 
203 
204 void DFS(Graph g, int i, vector<string> &v)
205 {
206    cout<<"进入遍历中"<<i<<":";
207    v.push_back(g.vexs[i]);
208    int j;
209    visited[i] = TRUE;
210    cout<<" 顶点:"<<g.vexs[i]<<endl;
211    //printf("%s ", g.vexs[i].c_str());                           //打印顶点,也可以其他操作
212    for(j = 0; j < g.numVertexes; j++)
213    {
214            cout<<"\t遍历点:"<<j<<"的状态"<<visited[j]<<" "<<"g.arc的值"<<g.arc[i][j]<<endl;
215        if(g.arc[i][j] == 1 && !visited[j])
216        {
217                   cout<<"\t\t\t\t   准备进入下一点:"<<j<<endl;
218                   cout<<"\t\t\t\t\t\t "<<i<<":"<<j<<":"<<g.arc[i][j]<<endl;
219           DFS(g,j,v);                  //对为访问的邻接顶点递归调用
220        }
221    }
222    cout<<"结束本次"<<i<<"遍历"<<endl;
223 }
224 
225 
226 
227 
228 
229 void DFSclear(Graph g,vector<string> &v)
230 {
231     int i;
232         cout<<endl;
233         cout<<"初始化所有顶点状态都是未访问过状态...."<<endl;
234     for(i = 0; i < g.numVertexes; i++)
235     {
236        visited[i] = FALSE;         //初始化所有顶点状态都是未访问过状态
237     }
238         v.clear();
239 }
240 
241 
242 
243 
244 void CreateGraph(Graph *g,Wing *ww,vector<string> &v)
245 {
246         #ifdef DEBUG
247              printf("刚才输入顶点数和边数为:%d %d\n", g->numVertexes, g->numEdges);
248         #endif
249     //设置顶点数组
250         for(int i=0;i<g->numVertexes;i++)
251         {
252                  g->vexs[i]=v[i];
253                  cout<<g->vexs[i]<<" ";
254                  //printf("%s ",g->vexs[i].c_str());
255         }     
256         cout<<endl;
257 
258 
259         //矩阵赋值
260         for(int k=0;k<WM;k++)
261         {
262                 int m=-1;
263                 int n=-1;
264                 m = locates(g,(ww+k)->d1);
265                 n = locates(g,(ww+k)->d2);
266 
267         if(n == -1 || m == -1)
268             {
269                fprintf(stderr, "there is no this vertex.\n");
270                return;
271             }
272             //printf("m=%d,n=%d\n",m,n);
273             g->arc[m][n] = (ww+k)->wv;
274             g->arc[n][m] = g->arc[m][n]; 
275         }
276 
277 }
278 
279 void init(Graph *g)
280 {
281         for(int i=0;i<g->numVertexes;i++)
282                 for(int j=0;j<g->numVertexes;j++)
283                 {
284                   g->arc[i][j]=0;
285                 }
286 }
287 
288 
289 
290 int locates(Graph *g,string sch)
291 {
292    int i = 0;
293    for(i = 0; i < g->numVertexes; i++)
294    {
295      if(g->vexs[i] == sch)
296      {
297          break;
298      }
299    }
300    if(i >= g->numVertexes)
301    {
302         return -1;
303     }
304    return i;
305 }
306 
307 void printGraph(Graph g)
308 {
309   printf("开始打印\n");
310   int i, j;
311   for(i = 0; i < g.numVertexes; i++)
312   {
313         for(j = 0; j < g.numVertexes; j++)
314         {
315           printf("%d  ", g.arc[i][j]);
316          }
317       printf("\n");
318   }
319 }
无向图-Prim

 

结果:

图-指尖上的舞蹈_第9张图片

=================================================================================

·Dijkstra:

图-指尖上的舞蹈_第10张图片图-指尖上的舞蹈_第11张图片  图-指尖上的舞蹈_第12张图片

 

原Dijkstra算法实现,只打印了最短路径结果,但个人觉得中间过程明细更重要,稍微改了一下。

  1 #include <iostream>
  2 #include <sstream>
  3 #include <fstream>
  4 #include <stdlib.h>
  5 #include <string.h>
  6 #include <vector>
  7 #include <typeinfo>
  8 #include <set>
  9 
 10 
 11 using namespace std;
 12 
 13 typedef string VertexType;                //顶点类型应由用户定义
 14 typedef int EdgeType;                   //边上的权值类型应由用户定义
 15  
 16 #define  DM 6           //顶点数
 17 #define  BM 8           //边数
 18 #define INF   9999999       //用9999999来代表无穷大
 19 #define DEBUG
 20 
 21 
 22 typedef struct
 23 {
 24    VertexType vexs[DM];            //顶点表
 25    EdgeType   arc[DM][DM];     //邻接矩阵,可看作边
 26    int numVertexes, numEdges;          //图中当前的顶点数和边数
 27 } Graph;
 28 
 29 typedef struct
 30 {
 31   char d1[2];
 32   char d2[2];
 33   int    wv;
 34 } Wing;
 35 
 36 typedef struct 
 37 {
 38     int r_id;
 39         int src;
 40         int des;
 41         double  ww;
 42 } Rd;
 43 
 44 int locates(Graph *g, string sch);
 45 void init(Graph *g);
 46 void printGraph(Graph g);
 47 void CreateGraph(Graph *g,Wing *ww,vector<string> &v);
 48 void DIJ(Graph g,int src,Rd rtt[]);
 49 
 50 int main()
 51 {
 52    //放原始图
 53    Wing *w=NULL;
 54    w=(Wing*)malloc(sizeof(Wing)*BM);
 55 
 56 
 57    //读原始图
 58    std::ios::sync_with_stdio(false);
 59    string line;
 60    string filename="./tu008.cfg";
 61    ifstream ifs;
 62    ifs.open(filename.c_str());
 63    int i=0;
 64    set<string> v2;
 65    while(getline(ifs,line))
 66    {
 67           istringstream strstm(line);
 68           string str1,str2,str3;
 69           strstm>>str1>>str2>>str3;
 70           strcpy((w+i)->d1,str1.c_str());
 71           strcpy((w+i)->d2,str2.c_str());
 72           (w+i)->wv=atoi(str3.c_str());
 73           v2.insert(str1);
 74           v2.insert(str2);
 75           i++;
 76    }
 77 
 78    //邻接矩阵创建图和顶点数组枚举创建
 79    Graph g;
 80    vector<string> v1;
 81 
 82    set<string>::iterator v2_it;
 83    for(v2_it=v2.begin();v2_it!=v2.end();v2_it++)
 84    {
 85          v1.push_back(*v2_it);
 86    }
 87 
 88    //设置顶点和边上限
 89    g.numVertexes=DM;
 90    g.numEdges=BM;
 91    
 92    //开始干活
 93    init(&g);
 94    CreateGraph(&g,w,v1);
 95    printGraph(g);
 96 
 97    //结束
 98    free(w);
 99 
100    //拓扑最短路径
101    Rd route[10];
102    DIJ(g,0,route);
103    
104 }
105 
106 
107 void DIJ(Graph g, int src,Rd rtt[])
108 {
109     int idMin = 0;
110         double dMin = 0;
111         double dTempMin = 0;
112         int rtc=0;  //路由表计数
113     
114         //距离定义,访问标记
115         double dDist[DM] = {0};
116         bool bFinalSet[DM] = {false};
117 
118         for (int i=0;i<DM;i++)
119     {
120             bFinalSet[i] = false;
121         dDist[i] = g.arc[src][i];
122                 //cout<<i<<":"<<bFinalSet[i]<<":"<<dDist[i]<<endl;
123                 cout<<"Route Detail:"<<src<<"-->"<<i<<","<<dDist[i]<<endl;
124                 //初始化路由表
125 
126                 rtt[i].r_id=i;
127                 rtt[i].src=src;
128                 rtt[i].des=i;
129                 rtt[i].ww=dDist[i];
130                 rtc=i;
131 
132     }
133     
134         cout<<endl;
135 
136     //起点定义
137         dDist[src]= 0;
138         bFinalSet[src] = true;
139 
140     for (int j=1;j<DM;j++)
141         {
142                 //打印路由表
143                 cout<<"打印路由表共"<<rtc+1<<"条:"<<endl;
144                 for(int z=0;z<=rtc;z++)
145                 {
146                         cout<<rtt[z].r_id<<":"<<rtt[z].src<<":"<<rtt[z].des<<":"<<rtt[z].ww<<endl;
147                 }
148 
149         //开始遍历
150                 dMin = INF;
151                 cout<<"--------------------------------"<<endl;
152                 for (int k=0; k<DM;k++)
153                 {
154                      if ((!bFinalSet[k]) && (dDist[k] <= dMin))
155                      {  
156                             cout<<"Round:"<<j<<"|k="<<k<<" dDist["<<k<<"]="<<dDist[k]<<endl;
157                         idMin = k;
158                         dMin = dDist[k];
159                      }
160                 }
161             bFinalSet[idMin] = true;
162                 cout<<"Round:"<<j<<"|最短路径 "<<src<<" and idMin="<<idMin<<" is:dMin="<<dMin<<endl;
163         
164             for (int l=0;l<DM;l++)
165                 {
166                      dTempMin = dMin + g.arc[idMin][l];
167                 //       cout<<"Round:"<<j<<"|g.arc["<<idMin<<"]["<<l<<"]:"<<g.arc[idMin][l]<<"|dTempMin:"<<dTempMin<<"|dDist["<<l<<"]:"<<dDist[l]<<endl;
168              if ((!bFinalSet[l]) && (dTempMin < dDist[l]))
169              {
170                                rtc++;
171                                    rtt[rtc]=rtt[idMin];
172                                    rtt[rtc].r_id=rtc;
173                                    rtt[rtc].src=idMin;
174                                    rtt[rtc].des=l;
175                                    rtt[rtc].ww=dTempMin;
176                                    cout<<"Round:"<<j<<"|Update dDist["<<l<<"],Route Detail "<<idMin<<"--->"<<l<<endl;
177                        dDist[l] = dTempMin;
178              }
179                          //cout<<"Round:"<<j<<"|Update ShortPath dDist["<<l<<"]:"<<dDist[l]<<endl;
180         }
181 
182 
183         }
184 }
185 
186 void CreateGraph(Graph *g,Wing *ww,vector<string> &v)
187 {
188         #ifdef DEBUG
189              printf("刚才输入顶点数和边数为:%d %d\n", g->numVertexes, g->numEdges);
190         #endif
191     //设置顶点数组
192         for(int i=0;i<g->numVertexes;i++)
193         {
194                  g->vexs[i]=v[i];
195                  cout<<g->vexs[i]<<" ";
196         }     
197         cout<<endl;
198 
199 
200         //矩阵赋值
201         for(int k=0;k<BM;k++)
202         {
203                 int m=-1;
204                 int n=-1;
205                 m = locates(g,(ww+k)->d1);
206                 n = locates(g,(ww+k)->d2);
207 
208         if(n == -1 || m == -1)
209             {
210                fprintf(stderr, "there is no this vertex.\n");
211                return;
212             }
213             //printf("m=%d,n=%d\n",m,n);
214             g->arc[m][n] = (ww+k)->wv;
215            // g->arc[n][m] = g->arc[m][n]; 
216         }
217 
218 }
219 
220 void init(Graph *g)
221 {
222         for(int i=0;i<g->numVertexes;i++)
223                 for(int j=0;j<g->numVertexes;j++)
224                 {
225                   if(i==j)
226                   {
227                   g->arc[i][j]=0;
228                   }
229                   else
230                   {
231                   g->arc[i][j]=INF;
232                   }
233                 }
234 }
235 
236 
237 
238 int locates(Graph *g,string sch)
239 {
240    int i = 0;
241    for(i = 0; i < g->numVertexes; i++)
242    {
243      if(g->vexs[i] == sch)
244      {
245          break;
246      }
247    }
248    if(i >= g->numVertexes)
249    {
250         return -1;
251     }
252    return i;
253 }
254 
255 void printGraph(Graph g)
256 {
257   printf("开始打印\n");
258   int i, j;
259   for(i = 0; i < g.numVertexes; i++)
260   {
261         for(j = 0; j < g.numVertexes; j++)
262         {
263           printf("%8d  ", g.arc[i][j]);
264          }
265       printf("\n");
266   }
267 }
有向图-最短路径

 

结果:

图-指尖上的舞蹈_第13张图片

 

·小结

  上述这些只是近期无聊研究的结果,大家伙轻拍砖~,^_^ ,午睡去了

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

你可能感兴趣的:(图)