Dijkstra算法求图的单源最短路径
2012-12-04 13:08
357 查看
源码下载:http://download.csdn.net/detail/nuptboyzhb/4848125
简介:
Dijkstra算法是已知网络的拓扑结构和各链路的长度,寻找从源节点到网络中其他各节点的最短路径。
设某个节点为源节点,每次寻找一个节点到源节点的最短路径,直至找到所有的节点。
以网络中的每一个节点作为源节点,分别使用最短路径算法,得出的结果就是全网的最短路径。
一. 图的表示和存储
在学习数据结构中,我们都知道,图有2种常见的表示形式:邻接矩阵和邻接表。如下图[1][2]所示
[图1] [图2]
对于无向图,如下图:它的连接矩阵的表示形式是一个实对称矩阵。如图3
[图3]
对于有向图,如下图表示:
图4
编程约定:
在编程时,我们通常有一下几种方法来代替无穷大
a.用一个很大的数来代替(比任何边的和都大)
b.用-1代替。图中的权值都不为负数,如果检查到负数,那么就知道它们之间没有直接相连
二. Dijkstra算法的步骤
设L(i,j)为i点与j点的权值
设L(i,j)为i点与j点的权值
1.初始化
设节点1为源节点,令N为已寻找到最短路径网络节点集合,N={1};
对所有不在N中的节点,有:
D(v)= L(i,j) ;若节点v与节点1直接相连
D(v)=∞;若节点v与节点1不直接相连
2.寻找一个不在N中的节点w,其D(w)值最小,把w加入到N中,然后对所有不在N中的节点v,
a.v节点之前与w不相邻(即D(v)=∞):
则D(v)更新为:D(v)=D(w)+L(w,v);
b.D(v)!=∞
则用[ D(v),D(w)+ L(w,v)]中较小的值去更新原有的D(v)值,即:
D(v)←Min[ D(v),D(w)+ L(w,v)] 。
3.重复步骤2,直至所有网络节点都在N中为止(循环次数=节点数)。
对图三中的迭代过程:
三. Dijkstra算法的实现
JAVA版本代码
C++ STL版本
简介:
Dijkstra算法是已知网络的拓扑结构和各链路的长度,寻找从源节点到网络中其他各节点的最短路径。
设某个节点为源节点,每次寻找一个节点到源节点的最短路径,直至找到所有的节点。
以网络中的每一个节点作为源节点,分别使用最短路径算法,得出的结果就是全网的最短路径。
一. 图的表示和存储
在学习数据结构中,我们都知道,图有2种常见的表示形式:邻接矩阵和邻接表。如下图[1][2]所示
[图1] [图2]
对于无向图,如下图:它的连接矩阵的表示形式是一个实对称矩阵。如图3
[图3]
对于有向图,如下图表示:
图4
编程约定:
在编程时,我们通常有一下几种方法来代替无穷大
a.用一个很大的数来代替(比任何边的和都大)
b.用-1代替。图中的权值都不为负数,如果检查到负数,那么就知道它们之间没有直接相连
二. Dijkstra算法的步骤
设L(i,j)为i点与j点的权值
设L(i,j)为i点与j点的权值
1.初始化
设节点1为源节点,令N为已寻找到最短路径网络节点集合,N={1};
对所有不在N中的节点,有:
D(v)= L(i,j) ;若节点v与节点1直接相连
D(v)=∞;若节点v与节点1不直接相连
2.寻找一个不在N中的节点w,其D(w)值最小,把w加入到N中,然后对所有不在N中的节点v,
a.v节点之前与w不相邻(即D(v)=∞):
则D(v)更新为:D(v)=D(w)+L(w,v);
b.D(v)!=∞
则用[ D(v),D(w)+ L(w,v)]中较小的值去更新原有的D(v)值,即:
D(v)←Min[ D(v),D(w)+ L(w,v)] 。
3.重复步骤2,直至所有网络节点都在N中为止(循环次数=节点数)。
对图三中的迭代过程:
三. Dijkstra算法的实现
JAVA版本代码
/* *@author: ZhengHaibo *web: blog.csdn.net/nuptboyzhb *mail: zhb931706659@126.com *2012-12-4 Nanjing njupt */ public class DijkstraTest{ public static void outPutMinPath(int []preIndex,int start,int end,int len) { int []path=new int[len];//定义存放路径的数组 int i=end; path[0]=i; int k=1; while (preIndex[i]!=start) { i=preIndex[i]; path[k]=i;//反向遍历 k++; } path[k]=start; for (int j = k; j >0; j--) { System.out.print("V"+path[j]+"->"); } System.out.println("V"+path[0]); } //查找权值为L1矩阵,起始点到终点的最短路径和最短距离 public static int dijkstra(int[][] L1, int start, int end) { boolean[] isLabel = new boolean[L1[0].length];// 是否标号 int[] N = new int[L1[0].length];// 所有标号的点的下标集合,以标号的先后顺序进行存储,实际上是一个以数组表示的栈 //int[] zhb_router =new int[L1[0].length]; int count = 0;//被标号顶点的顺序或数目 int[] Distance = L1[start].clone();// v0到各点的最短距离的初始值 int index = start;// 从初始点开始 N[count] = index;// 把已经标号的下标存入下标集中 int []preIndex=new int[L1[0].length];//用于记录最短路径树中的节点的前一个节点序号 for (int i = 0; i < preIndex.length; i++) {//初始化为起始接点 preIndex[i]=start; } isLabel[index] = true; while (count<L1[0].length){ // 第一步:标号v_start,即w[start][0]行中找到距离v_start最近的点 int min = Integer.MAX_VALUE; //找出与v_start距离最短的Distance的下标 for (int i = 0; i < Distance.length; i++) { if (!isLabel[i] && Distance[i] != -1 && i != index) { // 如果到这个点有边,并且没有被标号 if (Distance[i] < min) { min = Distance[i]; index = i;// 记录下这个下标 } } } if (index == end) {//已经找到当前点了,就结束查找 break; } isLabel[index] = true;//对点进行标号 count++;//增加一个标定的点 N[count] = index;// 把已经标号的下标存入下标集中 // 第二步:加入新的节点后,更新所有不在N中的节点的Distance for (int i = 0; i < Distance.length; i++) { //这个节点原来不可到达,刚加入的点和这个节点是互联的,并且不在N中 if (Distance[i] == -1 && L1[index][i] != -1&&!isLabel[i]) {//如果以前不可达,则现在可达了 Distance[i] = Distance[index] + L1[index][i]; preIndex[i]=index;//更新最短路径中当前接点的前一个接点 } else if (L1[index][i] != -1 && Distance[index] + L1[index][i] < Distance[i]) { // 如果以前可达,但现在的路径比以前更短,则更换成更短的路径 //即先从 Distance[i] = Distance[index] + L1[index][i]; preIndex[i]=index;//更新最短路径中当前接点的前一个接点 } }//每个节点到起始节点的最小距离更新完毕 } //如果全部点都遍历完,则Distance中存储的是开始点到各个点的最短路径 System.out.println("节点v"+start+"到节点v"+end+"的短距离为:"+(Distance[end]-Distance[start])); outPutMinPath(preIndex,start,end,Distance.length); return Distance[end]; } //查找权值为L1矩阵,起始点到所有点的最短路径和最短距离 //它与上面的Dijkstra函数的终止条件不同,这个是遍历所有节点后才结束 //而上面的算法只需要找到结束点end即结束。 public static void dijkstra(int[][] L1, int start) { boolean[] isLabel = new boolean[L1[0].length];// 是否标号 int[] N = new int[L1[0].length];// 所有标号的点的下标集合,以标号的先后顺序进行存储,实际上是一个以数组表示的栈 //int[] zhb_router =new int[L1[0].length]; int count = 0;//被标号顶点的顺序或数目 int[] Distance = L1[start].clone();// v0到各点的最短距离的初始值 int index = start;// 从初始点开始 N[count] = index;// 把已经标号的下标存入下标集中 int []preIndex=new int[L1[0].length];//用于记录最短路径树中的节点的前一个节点序号 for (int i = 0; i < preIndex.length; i++) {//初始化为起始接点 preIndex[i]=start; } isLabel[index] = true; while (true){ // 第一步:标号v_start,即w[start][0]行中找到距离v_start最近的点 int min = Integer.MAX_VALUE; //找出与v_start距离最短的Distance的下标 for (int i = 0; i < Distance.length; i++) { if (!isLabel[i] && Distance[i] != -1 && i != index) { // 如果到这个点有边,并且没有被标号 if (Distance[i] < min) { min = Distance[i]; index = i;// 记录下这个下标 } } } isLabel[index] = true;//对点进行标号 count++;//增加一个标定的点 if (count>=Distance.length) { break;//所有点已经遍历完 } N[count] = index;// 把已经标号的下标存入下标集中 // 第二步:加入新的节点后,更新所有不在N中的节点的Distance for (int i = 0; i < Distance.length; i++) { //这个节点原来不可到达,刚加入的点和这个节点是互联的,并且不在N中 if (Distance[i] == -1 && L1[index][i] != -1&&!isLabel[i]) {//如果以前不可达,则现在可达了 Distance[i] = Distance[index] + L1[index][i]; preIndex[i]=index;//更新最短路径中当前接点的前一个接点 } else if (L1[index][i] != -1 && Distance[index] + L1[index][i] < Distance[i]) { // 如果以前可达,但现在的路径比以前更短,则更换成更短的路径 //即先从 Distance[i] = Distance[index] + L1[index][i]; preIndex[i]=index;//更新最短路径中当前接点的前一个接点 } }//每个节点到起始节点的最小距离更新完毕 } //如果全部点都遍历完,则Distance中存储的是开始点到各个点的最短路径 for (int i = 0; i < Distance.length; i++) { System.out.println("节点v"+start+"到节点v"+i+"的短距离为:"+(Distance[i]-Distance[start])+" 最短路径如下:"); outPutMinPath(preIndex, start, i, Distance.length);//输出最短路径 } } /* *@author: ZhengHaibo *web: blog.csdn.net/nuptboyzhb *mail: zhb931706659@126.com *2012-12-4 Nanjing njupt */ public static void main(String[] args) { // 建立一个权值矩阵 int[][] L1 = { //测试数据1 无向图 实对称矩阵 { 0,2,-1,1,-1,-1}, { 2,0,3,2,-1,-1}, { -1,3,0,3,1,5 }, { 1,2,3,0,1,-1}, {-1,-1,1,1,0,2}, {-1,-1,5,-1,2,0}}; int[][] L2 = { //测试数据2 有向图 非对称矩阵 { 0,10,-1,30,100 }, { -1,0,50,-1,-1 }, { -1,-1,0,-1,10}, {-1,-1,20,0,60,}, {-1,-1,-1,-1,0}}; dijkstra(L1,0,5); dijkstra(L2,0,4); dijkstra(L1,0); dijkstra(L2, 0); /*//郑海波 2012年 * 运行结果 节点v0到节点v5的短距离为:4 * V0->V3->V4->V5 * 节点v0到节点v4的短距离为:60 * V0->V3->V2->V4 * 节点v0到节点v0的短距离为:0 最短路径如下: * V0->V0 * 节点v0到节点v1的短距离为:2 最短路径如下: * V0->V1 * 节点v0到节点v2的短距离为:3 最短路径如下: * V0->V3->V4->V2 * 节点v0到节点v3的短距离为:1 最短路径如下: * V0->V3 * 节点v0到节点v4的短距离为:2 最短路径如下: * V0->V3->V4 * 节点v0到节点v5的短距离为:4 最短路径如下: * V0->V3->V4->V5 * 节点v0到节点v0的短距离为:0 最短路径如下: * V0->V0 * 节点v0到节点v1的短距离为:10最短路径如下: * V0->V1 * 节点v0到节点v2的短距离为:50 最短路径如下: * V0->V3->V2 * 节点v0到节点v3的短距离为:30最短路径如下: * V0->V3 * 节点v0到节点v4的短距离为:60 最短路径如下: * V0->V3->V2->V4 */ } }
C++ STL版本
/* *@author: ZhengHaibo *web: blog.csdn.net/nuptboyzhb *mail: zhb931706659@126.com *2012-12-4 Nanjing njupt */ #include <iostream> #include<vector> #define MAXVALUE 65535 using namespace std; void OutputMinPath(vector<int> prevIndex,int startIndex,int endIndex) { vector<int> path; int i=endIndex; path.push_back(i); while(prevIndex[i]!=startIndex) { int k=prevIndex[i]; i=k; path.push_back(i); } path.push_back(startIndex); cout<<"---------------------"<<endl; cout<<"路径顺序如下:"<<endl; vector<int>::reverse_iterator rit; for (rit=path.rbegin();rit<path.rend()-1;rit++) { cout<<"v"<<*rit<<"->"; } cout<<"v"<<*rit<<endl; } void Dijkstra(vector< vector<int> > Lmatrix,int startIndex,int endIndex) { vector<int> Distance=Lmatrix[0]; vector<bool> isLabel(Distance.size(),false); vector<int> N; int count=0; int index = startIndex; N.push_back(index); isLabel[index]=true; vector<int> prevIndex(Distance.size(),startIndex); while (count<Distance.size()) { int min=MAXVALUE; for(int i=0;i<Distance.size();i++) { if (!isLabel[i]&&Distance[i]!=-1&&i!=index) { if (Distance[i]<min) { min=Distance[i]; index=i; } } } if (index==endIndex) { break; } isLabel[index]=true; count++; N.push_back(index); for (int j = 0;j<Distance.size();j++) { if (Distance[j]==-1&&Lmatrix[index][j]!=-1&&!isLabel[j]) { Distance[j]=Distance[index]+Lmatrix[index][j]; prevIndex[j]=index; } else if (Lmatrix[index][j]!=-1&&Distance[index]+Lmatrix[index][j]<Distance[j]) { Distance[j]=Distance[index]+Lmatrix[index][j]; prevIndex[j]=index; } } } cout<<"V"<<startIndex<<"到V"<<endIndex<<"的最短距离为:"<<Distance[endIndex]-Distance[startIndex]<<endl; OutputMinPath(prevIndex,startIndex,endIndex); } void Dijkstra(vector< vector<int> > Lmatrix,int startIndex) { vector<int> Distance=Lmatrix[0]; vector<bool> isLabel(Distance.size(),false); vector<int> N; int count=0; int index = startIndex; N.push_back(index); isLabel[index]=true; vector<int> prevIndex(Distance.size(),startIndex); while (true) { int min=MAXVALUE; for(int i=0;i<Distance.size();i++) { if (!isLabel[i]&&Distance[i]!=-1&&i!=index) { if (Distance[i]<min) { min=Distance[i]; index=i; } } } isLabel[index]=true; count++; if (count>=Distance.size()) { break; } N.push_back(index); for (int j = 0;j<Distance.size();j++) { if (Distance[j]==-1&&Lmatrix[index][j]!=-1&&!isLabel[j]) { Distance[j]=Distance[index]+Lmatrix[index][j]; prevIndex[j]=index; } else if (Lmatrix[index][j]!=-1&&Distance[index]+Lmatrix[index][j]<Distance[j]) { Distance[j]=Distance[index]+Lmatrix[index][j]; prevIndex[j]=index; } } } for (int i = 0; i < Distance.size(); i++) { cout<<"节点v"<<startIndex<<"到节点v"<<i<<"的短距离为:"<<(Distance[i]-Distance[startIndex])<<" 最短路径如下:"<<endl; OutputMinPath(prevIndex, startIndex, i);//输出最短路径 } } /* *@author: ZhengHaibo *web: blog.csdn.net/nuptboyzhb *mail: zhb931706659@126.com *2012-12-4 Nanjing njupt */ int main() { //测试数据1 无向图 实对称矩阵 int const N1=6; int L1[N1][N1] = { \ { 0,2,-1,1,-1,-1}, { 2,0,3,2,-1,-1}, { -1,3,0,3,1,5 }, { 1,2,3,0,1,-1}, {-1,-1,1,1,0,2}, {-1,-1,5,-1,2,0}}; //测试数据2 有向图 非对称矩阵 int const N2=5; int L2[N2][N2] = { \ { 0,10,-1,30,100 }, { -1,0,50,-1,-1 }, { -1,-1,0,-1,10}, {-1,-1,20,0,60,}, {-1,-1,-1,-1,0}}; vector< vector<int> > Lmatrix; vector<int> temp; int i,j; for (i=0;i<N1;i++)//将L1初始化到Lmatrix { for (j=0;j<N1;j++) { temp.push_back(L1[i][j]); } Lmatrix.push_back(temp); temp.clear(); } Dijkstra(Lmatrix,0,5); Dijkstra(Lmatrix,0); ////////////////////////////////////////////////////////////////////////// for (i=0;i<N2;i++)//将L1初始化到Lmatrix { for (j=0;j<N2;j++) { temp.push_back(L2[i][j]); } Lmatrix.push_back(temp); temp.clear(); } Dijkstra(Lmatrix,0,4); Dijkstra(Lmatrix,0); Lmatrix.clear(); ////////////////////////////////////////////////////////////////////////// return 1; } /* V0到V5的最短距离为:4 --------------------- 路径顺序如下: v0->v3->v4->v5 节点v0到节点v0的短距离为:0 最短路径如下: --------------------- 路径顺序如下: v0->v0 节点v0到节点v1的短距离为:2 最短路径如下: --------------------- 路径顺序如下: v0->v1 节点v0到节点v2的短距离为:3 最短路径如下: --------------------- 路径顺序如下: v0->v3->v4->v2 节点v0到节点v3的短距离为:1 最短路径如下: --------------------- 路径顺序如下: v0->v3 节点v0到节点v4的短距离为:2 最短路径如下: --------------------- 路径顺序如下: v0->v3->v4 节点v0到节点v5的短距离为:4 最短路径如下: --------------------- 路径顺序如下: v0->v3->v4->v5 V0到V4的最短距离为:2 --------------------- 路径顺序如下: v0->v3->v4 节点v0到节点v0的短距离为:0 最短路径如下: --------------------- 路径顺序如下: v0->v0 节点v0到节点v1的短距离为:2 最短路径如下: --------------------- 路径顺序如下: v0->v1 节点v0到节点v2的短距离为:3 最短路径如下: --------------------- 路径顺序如下: v0->v3->v4->v2 节点v0到节点v3的短距离为:1 最短路径如下: --------------------- 路径顺序如下: v0->v3 节点v0到节点v4的短距离为:2 最短路径如下: --------------------- 路径顺序如下: v0->v3->v4 节点v0到节点v5的短距离为:4 最短路径如下: --------------------- 路径顺序如下: v0->v3->v4->v5 Press any key to continue */
相关文章推荐
- Dijkstra算法(单源最短路径)
- dijkstra算法求解单源点最短路径
- 数据机构学习笔记(四) 图之单源最短路径Dijkstra算法
- Dijkstra算法---单源最短路径
- Dijkstra算法讲解(单源最短路径问题求解)
- 贪心算法——单源最短路径(Dijkstra算法)
- 单源最短路径复习--Dijkstra算法和Floyd算法
- 单源最短路径-Dijkstra算法 学习笔记
- 杭电 1874 单源最短路径 Dijkstra算法
- 图的单源最短路径Dijkstra算法
- Dijkstra算法(单源最短路径)
- 图_单源最短路径_ Dijkstra算法
- 单源最短路径问题之dijkstra算法
- 单源最短路径问题(Dijkstra算法)第五集
- 单源最短路径—Bellman-Ford和Dijkstra算法
- Dijkstra算法——求单源最短路径
- 越獄之权值非负单源最短路径问题-Dijkstra算法
- 【转】Dijkstra算法(单源最短路径)
- Dijkstra算法(单源最短路径)
- Dijkstra算法(单源最短路径)