图-指尖上的舞蹈
·背景
在大部分数据结构的讲义中,图一般出现在第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 }
结果:
=================================================================================
·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<<"\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 }
结果:
=================================================================================
·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\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 }
结果:
·小结
上述这些只是近期无聊研究的结果,大家伙轻拍砖~,^_^ ,午睡去了