zoukankan      html  css  js  c++  java
  • 图-指尖上的舞蹈

    ·背景

    在大部分数据结构的讲义中,图一般出现在第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<<"
    ---------------------------------------------------------------------"<<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<<"
    ---------------------------------------------------------------------"<<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<<"	遍历点:"<<j<<"的状态"<<visited[j]<<" "<<"g.arc的值"<<g.arc[i][j]<<endl;
    158        if(g.arc[i][j] == 1 && !visited[j])
    159        {
    160            cout<<"				   准备进入下一点:"<<j<<endl;
    161            cout<<"						 "<<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<<"	遍历点:"<<j<<"的状态"<<visited[j]<<" "<<"g.arc的值"<<g.arc[i][j]<<endl;
    193        if(g.arc[i][j] == 1 && !visited[j])
    194        {
    195                   cout<<"				   准备进入下一点:"<<j<<endl;
    196                   cout<<"						 "<<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
    ", 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.
    ");
    246                return;
    247             }
    248             //printf("m=%d,n=%d
    ",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("开始打印
    ");
    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("
    ");
    294   }
    295 }
    无向图

     结果:

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

    ·Prim:

           

    原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<<"	权值="<<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<<"	进入下一步:"<<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<<"	进入下一步:"<<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<<"	遍历点:"<<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<<"				   准备进入下一点:"<<j<<endl;
    181            cout<<"						  "<<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<<"	遍历点:"<<j<<"的状态"<<visited[j]<<" "<<"g.arc的值"<<g.arc[i][j]<<endl;
    215        if(g.arc[i][j] == 1 && !visited[j])
    216        {
    217                   cout<<"				   准备进入下一点:"<<j<<endl;
    218                   cout<<"						 "<<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
    ", 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.
    ");
    270                return;
    271             }
    272             //printf("m=%d,n=%d
    ",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("开始打印
    ");
    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("
    ");
    318   }
    319 }
    无向图-Prim

    结果:

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

    ·Dijkstra:

      

    原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
    ", 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.
    ");
    211                return;
    212             }
    213             //printf("m=%d,n=%d
    ",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("开始打印
    ");
    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("
    ");
    266   }
    267 }
    有向图-最短路径

    结果:

    ·小结

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

  • 相关阅读:
    byte在计算机中的存储方式--Double.byteValue()的输出结果思考
    启动Eclipse时An internal error occurred during: "Initializing Java Tooling".错误
    java实现两个int数交换
    cmd编译运行java
    java配置环境变量
    使用jQuery获取session中存储的list集合
    搭建ssm框架,可实现登录和数据展示以及增删改查
    java 生成UUID
    jQuery serialize()方法获取不到数据,alert结果为空
    SpringMVC架构的项目,js,css等静态文件导入有问题
  • 原文地址:https://www.cnblogs.com/zacard-orc/p/3598243.html
Copyright © 2011-2022 走看看