·背景

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

·分解

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

 图-指尖上的舞蹈

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

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

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

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

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

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

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

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

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

 

·前三项算法的举例

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

·DFS:

图-指尖上的舞蹈图-指尖上的舞蹈       图-指尖上的舞蹈

 

  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 }
无向图

相关文章:

  • 2022-12-23
  • 2022-12-23
  • 2021-07-25
  • 2022-12-23
  • 2021-08-27
  • 2021-08-18
  • 2022-02-05
  • 2021-10-09
猜你喜欢
  • 2021-10-12
  • 2021-05-30
  • 2021-08-08
  • 2021-05-15
  • 2021-10-16
  • 2021-09-08
相关资源
相似解决方案