并行dijkstra最短路径算法
- 格式:doc
- 大小:39.50 KB
- 文档页数:3
在交通网络中,常常会提出许多这样的问题:两地之间是否有路相通?在有多条通路的情况下,哪一条最近?哪一条花费最少等。
交通网络可以用带权图表示,图中顶点表示域镇,边表示两城之间的道路,边上权值可表示两城镇间的距离,交通费用或途中所需的时间等。
以上提出的问题就是带权图中求最短路径的问题,即求两个顶点间长度最短的路径。
最短路径问题的提法很多。
在这里仅讨论单源最短路径问题:即已知有向图(带权),我们希望找出从某个源点S∈V到G中其余各顶点的最短路径。
例如:下图(有向图G14),假定以v1为源点,则其它各顶点的最短路径如下表所示:图G14从有向图可看出,顶点v1到v4的路径有3条:(v1,v2,v4),(v1,v4),(v1,v3,v2,v4),其路径长度分别为:15,20和10。
因此v1到v4的最短路径为(v1,v3,v2,v4 )。
为了叙述方便,我们把路径上的开始点称为源点,路径的最后一个顶点为终点。
那么,如何求得给定有向图的单源最短路径呢?迪杰斯特拉(Dijkstra)提出按路径长度递增产生诸顶点的最短路径算法,称之为迪杰斯特拉算法。
迪杰斯特拉算法求最短路径的实现思想是:设有向图G=(V,E),其中,V={0,2,…,n-1},cost是表示G的邻接矩阵,G.arcs [i][j] .adj 表示有向边<i,j>的权。
若不存在有向边<i,j>,则G.arcs [i][j] .adj 的权为无穷大(这里取值为32767)。
设S是一个集合,其中的每个元素表示一个顶点,从源点到这些顶点的最短距离已经求出。
设顶点v0为源点,集合S的初态只包含顶点v0。
数组D记录从源点到其他各顶点当前的最短距离,其初值为D[i]= G.arcs[v0][i].adj ,i=1,…,n-1。
从S之外的顶点集合V-S 中选出一个顶点w,使D[w]的值最小。
于是从源点到达w只通过S 中的顶点,把w加入集合S中调整D中记录的从源点到V-S中每个顶点v的距离:从原来的D[v] 和D[w]+ G.arcs [w][v] .adj中选择较小的值作为新的D[v]。
迪杰斯特拉算法c语言从某个源点到其余各顶点的最短路径-回复如何用C语言实现Dijkstra算法来找出从某个源点到其余各顶点的最短路径。
第一步:了解Dijkstra算法的基本原理Dijkstra算法是一种解决单源最短路径的经典算法。
它通过不断更新顶点的最短距离来求解从源点到其他顶点的最短路径。
算法基于一个贪心策略,每次选择当前最短距离的节点进行松弛操作,并标记该节点为已访问。
具体而言,算法包括以下步骤:1. 初始化,设置源点距离为0,其他所有节点的距离设为无穷大。
2. 选择距离源点最近的节点作为当前节点,并将它标记为已访问。
3. 遍历当前节点的所有邻接节点,如果经过当前节点到达邻接节点的距离比已知的最短距离小,则更新该邻接节点的最短距离。
4. 重复步骤2和3,直到所有节点都被标记为已访问,或者所有节点的最短距离都已确定。
第二步:创建数据结构来表示图为了实现Dijkstra算法,我们需要使用图数据结构来表示顶点和它们之间的边。
在C语言中,我们可以使用邻接矩阵和邻接链表两种方式来表示图。
邻接链表相对而言更加灵活和高效,因此我们选择使用邻接链表来表示图。
我们可以创建一个结构体来表示顶点,其中包含了顶点的索引、距离以及指向邻接节点的指针。
另外,我们还需要创建一个结构体来表示边,其中包含了边的权重和指向目标顶点的指针。
第三步:实现Dijkstra算法的主要函数首先,我们需要编写一个用于初始化图的函数,其中包括创建顶点和边的操作。
具体而言,我们可以使用邻接链表,将每个顶点作为链表的头节点,链表中的每个节点表示一个边,其中包含目标顶点的索引、权重和指向下一条边的指针。
接下来,我们需要编写一个用于查找当前最短距离的函数。
在该函数中,我们遍历所有未访问的节点,并返回距离源点最近的节点。
然后,我们需要编写一个用于更新当前节点的邻接节点的最短距离的函数。
在该函数中,我们遍历当前节点的邻接节点,如果通过当前节点到达邻接节点的距离比已知的最短距离小,则更新该邻接节点的最短距离。
dijkstra最短路径算法详解
Dijkstra最短路径算法是一种常用的图算法,用于求解带权图中的单源最短路径问题,即从一个固定的源节点到图中的其他节点的最
短路径。
以下是详细的算法步骤:
1. 初始化
一开始,将源节点的距离设为0,其余节点的距离设置为正无穷,在未访问的节点集合中把源节点压入堆中。
2. 确定最短路径
从堆中取出未访问节点集合中距离源节点最近的节点v,标记其
为已访问。
之后,对于v的邻居节点w,计算从源节点到v再到w的距离,如果经过v的路径比已经计算得到的路径短,则更新路径。
更新
后的距离先暂时放入堆中,如果后边有更短的路径,则更新。
3. 重复第2步
重复第2步,直到取出的节点为终点节点,或者堆为空。
4. 算法结束
算法结束后,各节点的距离就是从源节点到它们的最短距离。
Dijkstra算法的复杂度是O(NlogN),其中N是节点个数。
其优
势在于只需要算一次即可得到所有最短路径,但是要求所有边的权值
必须非负,否则会导致算法不准确。
总之,Dijkstra算法是一种简单有效的最短路径算法,其实现也比较直观。
在处理如飞机和火车等交通路径规划问题中有较好的应用。
dijkstra算法java最短路径Dijkstra算法是一种用于寻找图中两个节点之间最短路径的算法。
它采用的是贪心策略,将图中的节点分为两个集合:已访问节点集S和未访问节点集T。
算法从源节点开始,每次从T中选择到源节点距离最短的节点加入S集合,并更新S集合中各节点到源节点的最短路径。
直到T集合中的节点全部加入S集合,算法结束。
Dijkstra算法的Java实现如下:●public class Dijkstra{●public static void main(String[]args){●创建图●Graph graph=new Graph();●graph.addVertex("A");●graph.addVertex("B");●graph.addVertex("C");●graph.addEdge("A","B",10);●graph.addEdge("A","C",20);●graph.addEdge("B","C",30);●计算最短路径●dijkstra(graph,"A");}●private static void dijkstra(Graph graph,String startVertex){●初始化●Set<String>visited=new HashSet<>();●Map<String,Integer>distances=new HashMap<>();●for(String vertex:graph.getVertices()){●distances.put(vertex,Integer.MAX_VALUE);}●distances.put(startVertex,0);●遍历所有节点●for(String vertex:graph.getVertices()){●找到未访问节点中距离源节点最小的节点●String nearestVertex=findNearestVertex(distances,visited);●将该节点加入已访问节点集合●visited.add(nearestVertex);●更新该节点到其他节点的最短路径●for(String neighbor:graph.getAdjacentVertices(nearestVertex)){●intnewDistance=distances.get(nearestVertex)+graph.getEdgeWeight(nearestVertex,neighbor ●if(newDistance<distances.get(neighbor)){●distances.put(neighbor,newDistance);}}}●输出结果●System.out.println("从"+startVertex+"到其他节点的最短路径:");●for(String vertex:graph.getVertices()){●System.out.println(vertex+"的最短路径是:"+distances.get(vertex));}}●private static String findNearestVertex(Map<String,Integer>distances,Set<String>visited){●int minDistance=Integer.MAX_VALUE;●String nearestVertex=null;●for(String vertex:distances.keySet()){●if(!visited.contains(vertex)&&distances.get(vertex)<minDistance){●minDistance=distances.get(vertex);●nearestVertex=vertex;}}●return nearestVertex;}}该算法的工作原理如下:1.初始化距离表,将所有节点的距离初始化为无穷大。
单源最短路径问题并行算法分析实验报告一、实验名称单源最短路径问题并行算法分析。
二、实验目的分析单源最短路径Dijkstra并行算法和MPI源程序,并分析比较Dijkstra并行算法和Moore并行算法的性能。
三、实验内容1、分析单源最短路径Dijkstra并行算法和MPI源程序。
2、分析单源最短路径问题的Moore并行算法,比较两种并行算法的性能。
四、实验步骤1、问题描述单源最短路径问题即指:已知一个n结点有向图G=(V,E)和边的权函数c(e),求由G中某指定结点v0到其他各个结点的最短路径。
这里还假定所有的权值都是正的。
2、比较串行Dijkstra算法和Moore算法2.1、Dijkstra算法基本思想假定有一个待搜索顶点表VL,初始化时做:dist(s)←0;dist(i)←∞(i≠s);VL←V。
算法执行时,每次从VL(≠Φ)中选取这样一个顶点u,它的dist(u)值最小。
将选出的u作为搜索顶点,若<u,v>∈E,而且dist(u)+w(u,v)<dist(v),则更新dist(v)为dist(u)+w(u,v),直到VL=Φ时算法终止。
算法描述如下:输入:加权邻接矩阵W,约定i,j之间无边连接时w(i,j)=∞,且w(i,i)=∞;输出:dist(1:n),其中,dist(i)表示顶点s到顶点i的最短路径(1≤i≤n)。
begin/*初始化*/(1)dist(s)←0;(2)for i←1 to n doif i≠s then dist(i)←∞endifendfor;(3)VL←V;(4)for i←1 to n do /*找最短距离*/(5)find a vertex u∈VL,such that dist(u) is minimal;(6)for each(<u,v>∈E) ∧(v∈VL) doif dist(u)+w(u,v)<dist(v) thendist(v)←dist(u)+w(u,v)endifendfor;(7)VL←VL-{u}endforend.2.2、Moore算法的基本思想设源点为s∈V,从s到其它各顶点的最短路径长度用一个一维数组dist存储。
《求解最短路径:应用迪杰斯特拉算法》一、介绍Dijkstra算法的概念和基本原理Dijkstra算法是一种用于解决最短路径问题的算法,它由荷兰计算机科学家Edsger Dijkstra在1959年发明,用于求解从源点到其他所有结点的最短路径。
它的基本原理是:在一张图中,从源点到每一个结点的最短路径是从源点开始,经过最少的边到达每一个结点的路径。
Dijkstra算法的实现过程中,首先要建立一个有向图,该图由顶点和边组成,每条边都有一个权值,表示从一个顶点到另一个顶点的距离。
然后,从源点开始,每次选择最小权值的边,继续查找下一个顶点,直到找到终点。
最后,将所有路径之和求出,即为源点到目标点的最短路径。
举例来说,假如有一张有向图,其中有A,B,C,D四个结点,以及AB,AC,BD,CD四条边,其中AB,AC,BD边的权值分别为2,3,1,CD边的权值为4。
如果要求求出从A到D的最短路径,则可以使用Dijkstra算法,首先从A出发,选择权值最小的边,即BD,则A-B-D的路径长度为3,接着从B出发,选择权值最小的边,即CD,则A-B-D-C的路径长度为7,因此,从A到D的最短路径为A-B-D,路径长度为3。
Dijkstra算法的优点是算法简单,实现方便,时间复杂度低,它可以用于解决路径规划,车辆调度,网络路由等问题,同时,它也可以用于解决复杂的最短路径问题。
因此,Dijkstra算法在计算机科学中有着重要的应用价值。
二、讨论Dijkstra算法的应用及其优势Dijkstra算法是一种用于解决最短路径问题的算法,它的应用和优势非常广泛。
首先,Dijkstra算法可以用于解决交通路网中的最短路径问题。
例如,在一个城市的交通路网中,如果一个乘客要从一个地方到另一个地方,那么他可以使用Dijkstra算法来查找最短的路径。
这样可以节省乘客的时间和金钱,也可以减少拥堵。
此外,Dijkstra算法还可以用于解决计算机网络中的最短路径问题。
c++ 遍历所有点且距离最短_最短路径问题dijkstra算法详解一、问题概述在图论中,最短路径问题是一个重要的研究课题,它涉及到从一个节点到另一个节点的最短路径的寻找。
Dijkstra算法是一种用于解决最短路径问题的经典算法,它可以高效地遍历图中的所有节点,并找到从起始节点到目标节点的最短路径。
二、Dijkstra算法详解1. 算法思想Dijkstra算法的基本思想是:对于图中的每个节点,选择距离起始节点最近的节点,并将其标记为已访问。
然后,从已访问的节点中选择下一个距离起始节点最近的节点,并将其标记为已访问。
重复这个过程,直到遍历完所有的节点。
在每一步中,算法都会更新节点之间的距离信息,以使得结果更加精确。
2. 算法步骤(1) 初始化:将起始节点的距离设置为0,将所有其他节点的距离设置为无穷大。
将起始节点标记为已访问。
(2) 遍历所有相邻节点:对于每个已访问的节点,遍历其所有相邻节点,并更新它们到起始节点的距离。
对于每个相邻节点,如果通过该相邻节点到达起始节点的距离比当前距离更短,则更新该相邻节点的距离。
(3) 终止条件:当没有未访问的节点时,算法终止。
此时,每个节点的最短路径已经确定。
3. C语言实现以下是一个简单的C语言实现Dijkstra算法的示例代码:```c#include <stdio.h>#include <stdlib.h>#define MAX_VERTICES (100) // 最大顶点数int minDistance[MAX_VERTICES]; // 存储最小距离的数组int dist[MAX_VERTICES]; // 存储每个节点到起点的实际距离的数组bool visited[MAX_VERTICES]; // 标记每个节点是否已访问的数组int src; // 起点int V; // 顶点数void dijkstra(int G[MAX_VERTIXE][MAX_VERTICES], int src) {V = G[0].size(); // 获取顶点数for (int i = 0; i < V; i++) {dist[i] = INT_MAX; // 初始化所有顶点到起点的距离为无穷大visited[i] = false; // 所有顶点未访问}dist[src] = 0; // 起点的距离为0for (int count = 0; count < V - 1; count++) {int u = vertex_selection(G, dist, visited); // 选择当前距离最小的顶点uvisited[u] = true; // 将u标记为已访问for (int v = 0; v < V; v++) { // 遍历u的所有邻居顶点if (!visited[v] && (dist[v] > dist[u] + G[u][v])) { // 如果未访问且通过u到达v的距离更短dist[v] = dist[u] + G[u][v]; // 更新v的距离信息}}}}int vertex_selection(int G[MAX_VERTICES][MAX_VERTICES], int dist[], bool visited[]) {int minIdx = 0, minDist = INT_MAX;for (int v = 0; v < V; v++) { // 遍历所有顶点vif (!visited[v] && minDist > dist[v]) { // 如果未访问且当前距离更短minDist = dist[v];minIdx = v; // 记录最小距离和对应的顶点索引}}return minIdx; // 返回最小距离对应的顶点索引}```三、应用场景与优化方法Dijkstra算法适用于具有稀疏权重的图,它可以高效地找到最短路径。
Dijkstra算法求解单源最短路径问题一、单源最短路径问题描述给定一个带权有向图G=(V,E),其中每条边的权都是非负数。
给定V中的一个顶点,称为源。
计算从源到所有其他定点的最短路径长度。
这里的路径长度就是指各边权之和。
该问题称为单源最短路径问题(Single-Source Shortest Paths)。
二、Dijkstra算法思想将图G中所有的顶点V分成两个顶点集合S和T。
以v为源点已经确定了最短路径的终点并入S集合中,S初始时只含顶点v, T则是尚未确定到源点v最短路径的顶点集合。
然后每次从T集合中选择S集合点中到T路径最短的那个点,并加入到集合S中,并把这个点从集合T删除。
直到T集合为空为止。
三、算法描述(步骤)1、选一顶点v为源点,并视从源点v出发的所有边为到各顶点的最短路径:①记录从源点v到其它各顶点的路径长度数组dist[],开始时,dist是源点v到顶点i的直接边长度,即dist中记录的是邻接阵的第v行。
②设一个用来记录从源点到其它顶点的路径数组path[],path中存放路径上第i个顶点的前驱顶点。
2、在上述的最短路径dist[]中选一条最短的,并将其终点(即<v,k>)k加入到集合s中。
3、调整T中各顶点到源点v的最短路径。
因为当顶点k加入到集合s中后,源点v到T中剩余的其它顶点j就又增加了经过顶点k到达j的路径,这条路径可能要比源点v到j原来的最短的还要短。
调整方法是比较dist[k]+g[k,j]与dist[j],取其中的较小者。
4、再选出一个到源点v路径长度最小的顶点k,从T中删去后加入S中,再回去到第三步,如此重复,直到集合S中的包含图G的所有顶点。
四、算法实现(数据结构)1、算法实现输入:一个大于1的整数n.输出:●一个随机生成的有向图G=(V,E),对于每一条边,有一个非负数字c(u,v)与之相关。
●对于每个顶点v∈V,得到从v0到v的最短路径的长度。
并行dijkstra最短路径算法
一,并行算法设计与分析
1.1 并行化思路
串行的dijkstra算法有两层N次循环,第一层循环必须得按次序执行,不可并行。
那么只有将第二层循环并行。
第二层循环有两个N次的循环,第一次循环是求dist数组的最小值。
复杂度为O(N)
第二次循环是更新dist数组的值,复杂度也是O(N)。
所以串行的总复杂度为O(N*N)
那么必须将这两次循环都并行才可以降低复杂度。
1.2 求最小值的并行方法
假设有p个处理器,N个顶点。
给每个处理器分配N/p个顶点,求出局部的最小值,复杂度为O (N/p)。
然后后一半的处理器将自己的最小值发送给第前p/2个处理器。
前一半处理器接收到传来的值后,与局部的最小值比较,作为新值。
继续循环,直到剩下一个处理器为止。
注意:若p为偶数,则进行一次合并后,还剩p/2个处理器。
若p为奇数,则进行一次合并后,还剩p/2+1个处理器
复杂度为O (N/p+logp)
1.3 更新dist数组的并行方法
给每个处理器分配N/p个节点。
设选取的dist最小的顶点为u。
for(j=0;j<mynum;j++)
{
if dist[u]+w[u][j]<dist[j] then dist[j]= dist[u]+w[u][j];
}
采用行块带状划分,这是为了可以连续的传送邻接矩阵。
所以不采用行循环带状划分。
复杂度为O (N/p)
1.4 算法总复杂度
并行的dijkstra算法复杂度为O (N*(N/p+logp+N/p))=O (N*N/p+Nlogp)
二,行块带状划分方法
改进之前的代码采用此方法
比如5个处理器P0,P1,P2,P3,P4。
12个顶点
划分方法如下图所示
P1负责计算dist[0~2]
P2负责计算dist[3~5]
P3负责计算dist[6~8]
P4负责计算dist[9~11]
P1需要矩阵W[0~2][0~11]
P2需要矩阵W[3~5][0~11]
P3需要矩阵W[6~8][0~11]
P4需要矩阵W[9~11][0~11]
三,算法改进
3.1 无需单独分出一个处理器读数据
实际上当0号处理器读完邻接矩阵,并且初始化好其它处理器后,也可以参与并行dijkstra算法求解。
而不必将其闲置下来。
3.2 负载均衡
3.2.1 原先的分配方法
比如nodenum=100,groupsize=4,则编号依次为0,1,2,3。
0号进程不分配顶点则按原先的方法ep=34;分配的顶点数依次为34,34,32,
显然保证负载最均衡的分配应该为34,33,33
3.2.2 改进的分配方法
ep = nodenum/group_size;
mod=nodenum%group_size;
if(my_rank<mod) mynum=ep+1;
else mynum=ep;
这样可以保证任意两个处理器之间的任务数最多差1
计算全局节点编号的方法如下:比如i号进程中的局部编号j的节点,全局编号id为:If(i<mod)
{
id=(ep+1)*i+j;
}
else
{
id=(ep+1)*mod+ep*(i-mod)+j;
}
3.3 适用范围局限性
3.3.1 行块带状划分仅适用于对称矩阵的情况
num + W(j,index) < dist[j]实际上应该为num + W(index,j) < dist[j]。
若为对称邻接矩阵W(index,j) =W(j,index)。
3.3.2 改进方法:列块带状划分
若要对非对称邻接矩阵也适用,最好采用列块带状划分。
如图所示:
P1
P2负责计算dist[3~5]
P3负责计算dist[6~8]
P4负责计算dist[9~11]
P1需要矩阵W [0~11] [0~2]
P2需要矩阵W [0~11] [3~5]
P3需要矩阵W [0~11] [6~8]
P4需要矩阵W [0~11] [9~11]
这样发送的时候需要逐行发送,每行又分成p段发送。
3.4在求局部最小值时,可用堆的思想
可以将该部分复杂度将低为O( log(N/p))
还未编码。
四,改进测试
原先的对称邻接矩阵的数据测试全部通过。
附加测试数据:test文件如下
3
0 1 4
3 0 2
1 5 0
正确的结果应该为:
Dist[0][0]=0;
dist[0][1]=1;
dist[0][2]=3;
但改进之前的代码求出的值却是错误的。