图的更多相关算法-2(最短路径)
2013-04-22 14:26
232 查看
void DispPath(int path[],int begin, int end) //此函数是输出从begin节点到end节点最短的路径 { int ivar = 0; ivar = path[end]; cout<<"path is :"<<end<<' '; while(ivar != 0) { cout<<ivar<<' '; ivar = path[ivar]; } cout<<begin<<endl; } /* 此算法求节点距离其他节点的最短距离 s[i] == 1数组表示节点i在 s中不再 U中 dist[i]数组保存从begin到i节点的路径最小值 path[i]数组保存的是路径中在i节点前面的节点的值 思路: 在dist数组中查找在s数组中最短的路径的值,把找到的节点当做中间节点, 如果通过中间节点的路径比直达的路径或原先的路径短就进行替换 整个查找中间节点的操作是在dist数组中进行的 此算法与普利姆算法的区别是当找到中间节点后,此算法会由中间节点计算权的值,并进行相关的计算 而普利姆算法则是利用中间的修正候选边 普利姆算法中的lowcost保存的是两个顶点之间的最短路径 而狄更拉斯算法中的 dist数组保存的是初始顶点到其他顶点之间的最短路径,中间可以有节点存在即不是直达的节点 */ void Dijkstra(MGraph mg, int begin) { int loop1 = 0, count = 0, min = 1000, node = 0, path[MAXSIZE]; //path[i] 保存的是从begin 到i的路径中,位于 i前面的一个节点的值 int s[MAXSIZE], dist[MAXSIZE]; //s数组用以说明顶点的位置,当s[i] == 1的时候,说明顶点i在s中, 当s[i] == 0 的时候说明顶点在U中 //dist[i]数组用以保存从顶点begin 到 顶点为i的最短距离 for(loop1 = 0; loop1 < MAXSIZE; ++loop1) s[loop1] = 0; s[begin] = 1; for(loop1 = 0; loop1 < mg.n; ++loop1) { dist[loop1] = mg.edges[begin][loop1]; //dist[i] == 0的话,表示从 顶点begin 到 i节点不可到达 if(mg.edges[begin][loop1] == 0) //此处为path赋初值,如果begin到节点loop1可直达,则path为0 代表这个路径的前一个节点是begin节点本身, 否则的话path初始化为-1 ,代表没有路径 { path[count] = -1; ++count; } else { path[count] = 0; ++count; } } path[begin] = 0; count = 1; while(count < mg.n) { min = 1000; for(loop1 = 0; loop1 < mg.n; ++loop1) //此处进行查找最短的路径,条件是节点在U中,并且从begin到节点必须可以到达 { if(s[loop1] == 0 && dist[loop1] != 0 && min > dist[loop1]) { min = dist[loop1]; node = loop1; } } cout<<"Visiting node "<<node<<endl; s[node] = 1; //node为找到的节点 for(loop1 = 1; loop1 < mg.n; ++loop1) //此步骤是以找到的node节点为点,循环遍历与node直接相邻的量 { if(node != loop1 && mg.edges[node][loop1] != 0)//条件是不遍历自己, 并且那个节点与node节点应该可直达 { if(dist[loop1] == 0 ) //此处表示如果begin节点到loop1节点不能直达的话,就直接把经过node节点的距离当做最短距离 { dist[loop1] = dist[node] + mg.edges[node][loop1]; path[loop1] = node;} else if((dist[node] + mg.edges[node][loop1] ) < dist[loop1]) //否则的话,就进行判断如果进过node节点的路径长度小于直达的路径长度,进把距离的值重新赋值 { dist[loop1] = dist[node] + mg.edges[node][loop1]; path[loop1] = node;} } } ++count; } for(loop1 = 0; loop1 < mg.n; ++loop1) { cout<<"shortest path to "<<loop1<<" is "<<dist[loop1]<<endl; } DispPath(path,begin,6); } /* 采用弗洛伊德算法求每对顶点之间的最短路径 A[i][j]数组用以保存从i节点到j节点之间的最短路径,初始的值为顶点之间的权值 path[i][j]数组用以保存上一个节点的编号,即中间节点的编号,初始化的值为-1,表示没有中间节点 其步骤是: 1. 确定顶点i到j之间是否有通过0节点的路径,如果有的话,此时表示A[i][0] != 0 A[0][j] != 0 成立,然后判断这两段的长度是否比直达的长度小,如果小的话,就进行最短路径的替换(A数组保存的最短的路径),同时把path数组相应的节点置为0,表示从节点i到节点j之间存在一个中间节点为0 2. 考察顶点i到j之间是否有通过1节点的路径,如果有的话,即按照上面的步骤进行,否则直接跳过 3. 重复上述步骤2 通过比较知道:狄克斯特拉算法是求某个特定的顶点到其余顶点之间的最短路径 此算法表现的是特定的顶点与其余顶点之间的关系 而弗洛伊德算法则是求每对顶点之间的最短路径 此算法表现的是定点与顶点的关系 */ void Floyd(MGraph mg) { int path[MAXSIZE][MAXSIZE], A[MAXSIZE][MAXSIZE]; //path[i][j]数组保存的是从顶点i到顶点j中间节点编号不大于k的路径的上一个节点的编号 int ivar = mg.n, loop1 = 0, loop2 = 0, loop3 = 0; //A[i][j]数组保存的是从i到j的最短距离 for(loop1 = 0; loop1 < ivar; ++loop1) for(loop2 = 0; loop2 < ivar; ++loop2) { path[loop1][loop2] = -1; A[loop1][loop2] = mg.edges[loop1][loop2]; //对A数组进行初始化为边的权值,0表示两个顶点之间不可以直达或没路径 } for(loop1 = 0; loop1 < ivar; ++loop1) { for(loop2 = 0; loop2 < ivar; ++loop2) for(loop3 = 0; loop3 < ivar; ++loop3) {//此处应该以A数组为对象,不应该以mg.edges数组为对象。 // if(loop2 != loop3 && mg.edges[loop2][loop1] != 0 && mg.edges[loop1][loop3] != 0 && (A[loop2][loop3] == 0 || (mg.edges[loop2][loop1] + mg.edges[loop1][loop3]) < A[loop2][loop3])) if(loop2 != loop3 && A[loop2][loop1] != 0 && A[loop1][loop3] != 0 && (A[loop2][loop3] == 0 || (A[loop2][loop1] + A[loop1][loop3]) < A[loop2][loop3])) { A[loop2][loop3] = A[loop2][loop1] + A[loop1][loop3]; path[loop2][loop3] = loop1; } } for(loop2 = 0; loop2 < ivar; ++loop2) { for(loop3 = 0; loop3 < ivar; ++loop3) cout<<A[loop2][loop3]<<' '; cout<<endl; } cout<<endl; } } void MinTree(MGraph mg,int begin) { int dist[MAXSIZE], path[MAXSIZE], v[MAXSIZE]; int loop1 = 0, count = 1,node = 0, min = 10000, pre = 0,ivar = mg.n; for(loop1 = 0; loop1 < ivar; ++loop1) { v[loop1] = 0; dist[loop1] = mg.edges[begin][loop1]; if(mg.edges[begin][loop1] != 0) { path[loop1] = begin; } else { path[loop1] = -1; } } v[begin] = 1; count = 1; while(count < ivar) { min = 10000; for(loop1 = 0; loop1 < ivar; ++loop1) { if(v[loop1] == 0 && dist[loop1] != 0 && min > dist[loop1]) { node = loop1; min = dist[loop1]; } } v[node] = 1; for(loop1 = 0; loop1 < ivar; ++loop1) { if(mg.edges[node][loop1] != 0 && (dist[loop1] == 0 || (dist[node] + mg.edges[node][loop1]) < dist[loop1] )) { dist[loop1] = mg.edges[node][loop1] + dist[node]; path[loop1] = node; } } ++count; } for(loop1 = 0; loop1 < ivar; ++loop1) { if(v[loop1] == 1 && loop1 != begin) { pre = path[loop1]; cout<<"line is "<<pre<<" to "<<loop1<<" weight is "<<mg.edges[pre][loop1]<<endl; } } } void Centerp(MGraph mg) { int loop1 = 0, loop2 = 0, loop3 = 0, max = -1, maxindex = 0, ivar = mg.n; int A[MAXSIZE][MAXSIZE], path[MAXSIZE][MAXSIZE]; for(loop1 = 0; loop1 < ivar; ++loop1) for(loop2 = 0; loop2 < ivar; ++loop2) { A[loop1][loop2] = mg.edges[loop1][loop2]; path[loop1][loop2] = -1; } for(loop1 = 0; loop1 < ivar; ++loop1) for(loop2 = 0; loop2 < ivar; ++loop2) for(loop3 = 0; loop3 < ivar; ++loop3) { if(A[loop2][loop1] != 0 && A[loop1][loop3] != 0 && (A[loop2][loop3] == 0 || (A[loop2][loop1] + A[loop1][loop3]) < A[loop2][loop3]) ) { A[loop2][loop3] = A[loop2][loop1] + A[loop1][loop2]; path[loop2][loop3] = loop1; } } for(loop1 = 0; loop1 < ivar; ++loop1) { for(loop2 = 0; loop2 < ivar; ++loop2) { if(max < A[loop2][loop1]) { max = A[loop2][loop1]; maxindex = loop1; } } } cout<<"the center node is : "<<maxindex<<endl; }
本文出自 “赛” 博客,请务必保留此出处http://saibro.blog.51cto.com/2052408/1183644
相关文章推荐
- 算法学习-最短路径条数问题(队列相关)
- 更多和最短路径相关的问题
- 更多和最短路径相关的问题
- 最短路径问题的相关算法
- poj 1273 Drainage Ditches(最大费用流+最短增广路径算法)
- 最短路径算法 模板_Dijkstra_Bellman.ford_Floyd_spfa
- Dijkstra最短路径算法
- 最短路径算法Dijkstra && SPFA && Floyd 代码实现模板
- 单源最短路径(算法导论24章)
- 图之单源Dijkstra算法、带负权值最短路径算法
- 图的遍历、拓扑排序、最短路径算法
- 【原】单源最短路径快速算法(spfa)的python3.x实现
- 最短路径 Floyd算法 Dijkstra算法 Bellman-Ford(贝尔曼)算法
- 最短路径算法-迪杰斯特拉Dijkstra算法
- Floyd 算法求多源最短路径-打印最短路径
- 华为机试 地铁换乘问题(最短路径算法)
- dijsk最短路径算法(matlab)
- 单源最短路径:Dijkstra 算法 Bellman_Ford 算法 SPFA 算法
- 图算法:2、计算带有负权值的单源最短路径:Bellman-Ford算法
- 趣味算法-城市之间最短路径