迪杰斯特拉算法

来源:互联网 发布:网络电话录音 编辑:程序博客网 时间:2024/05/01 14:17

定义

迪杰斯特拉算法用于计算图中,某一个顶点vi到另外一个顶点vj的最短路径,因为计算从vi到vj的最短路径实际需要计算出vi到vj之前的所有顶点的最短路径,所以实际的计算可能会附带得出vi到图中一部分节点的最短路径,而且这种“附带”的结果是必需的。

算法过程如下:

设置出发顶点为v,顶点集合V{v1,v2,vi...},v到V中各顶点的距离构成距离集合Dis,Dis{d1,d2,di...},Dis集合记录着v到图中各顶点的距离(到自身可以看作0,v到vi距离对应为di)

1、从Dis中选择值最小的di并移出Dis集合,同时移出V集合中对应的顶点vi,此时的v到vi即为最短路径。

2、更新Dis集合,更新规则为:比较v到V集合中顶点的距离值,与v通过vi到V集合中顶点的距离值,保留值较小的一个(同时也应该更新顶点的前驱节点为vi,表明是通过vi到达的)。

3、重复执行两步骤,直到最短路径顶点为目标顶点即可结束。

示例


给{A,B,C,D,E,F,G}对应序号为{0,1,2,3,4,5,6},演示从G顶点,即序号6到图中各顶点的最短路径。

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

最短路径:G

顶点前驱:G->A,G->B,G->E,G->F

到各顶点距离:A:2,B:3,E:4,F:6

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

最短路径:A

顶点前驱:G->A,G->B,G->E,G->F

到各顶点距离:A:2,B:3,C:9,E:4,F:6

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

最短路径:A,B

顶点前驱:G->A,G->B,B->D,G->E,G->F

到各顶点距离:A:2,B:3,C:9,D:12,E:4,F:6

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

最短路径:A,B,E

顶点前驱:G->A,G->B,B->D,G->E,G->F

到各顶点距离:A:2,B:3,C:9,D:12,E:4,F:6

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

最短路径:A,B,E,F

顶点前驱:G->A,G->B,F->D,G->E,G->F

到各顶点距离:A:2,B:3,C:9,D:10,E:4,F:6

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

最短路径:A,B,C,E,F

顶点前驱:G->A,G->B,A->C,F->D,G->E,G->F

到各顶点距离:A:2,B:3,C:9,D:10,E:4,F:6

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

最短路径:A,B,C,D,E,F

顶点前驱:G->A,G->B,A->C,F->D,G->E,G->F

到各顶点距离:A:2,B:3,C:9,D:10,E:4,F:6

参考代码

class t{      public static void main(String[] args){          char[] vertex=new char[]{'A','B','C','D','E','F','G'}; //顶点数组          int[][] matrix=new int[7][];     //邻接矩阵          final int N=65535;          matrix[0]=new int[]{N,5,7,N,N,N,2};          matrix[1]=new int[]{5,N,N,9,N,N,3};          matrix[2]=new int[]{7,N,N,N,8,N,N};          matrix[3]=new int[]{N,9,N,N,N,4,N};          matrix[4]=new int[]{N,N,8,N,N,5,4};          matrix[5]=new int[]{N,N,N,4,5,N,6};          matrix[6]=new int[]{2,3,N,N,4,6,N};          Graph G=new Graph(vertex,matrix);  //构建图对象          //上述为测试用例          G.dsj(6);    }  }  class Graph{private char[] vertex; //顶点数组private int[][] matrix;//邻接矩阵private Visited_vertex vi;//已访问的顶点集合public Graph(char[] vertex,int[][] matrix){this.vertex=vertex;this.matrix=matrix;}public void dsj(int index){//迪杰斯特拉算法计算最短路径vi=new Visited_vertex(vertex.length,index);//初始化访问顶点集合对象update(index);//更新index下标顶点到周围顶点的距离与周围顶点的前驱顶点vi.show();//查看中间过程for(int j=1;j<vertex.length;j++){index=vi.updateArr();//选择并返回新的访问顶点update(index);//更新从出发顶点到index周围各顶点的距离vi.show();}}private void update(int index){//更新从出发顶点到index周围各顶点的距离int len=0;for(int j=0;j<matrix[index].length;j++){/*下面这个判断条件是指:j顶点还没有被访问,并且从出发顶点到index顶点的距离,加上从index顶点到j顶点的距离,小于从出发顶点到j顶点的距离*/len=vi.getDis(index)+matrix[index][j];if(!vi.in(j)&&len<vi.getDis(j)){vi.updatePre(j,index);//更新j顶点的前驱为index节点vi.updateDis(j,len);//更新出发节点到j顶点的距离}}}}class Visited_vertex{//已访问顶点集合public int[] already_arr;//已访问则对应下标上赋值为1,默认为0public int[] pre_visited;//每个下标对应的存储值为前一个顶点下标public int[] dis;//记录出发顶点到其他所有顶点的距离public Visited_vertex(int length,int index){this.already_arr=new int[length];this.pre_visited=new int[length];this.dis=new int[length];Arrays.fill(dis,65535);//设置初始距离already_arr[index]=1;//设置出发顶点为已访问dis[index]=0;//设置出发顶点访问距离为0}public int updateArr(){//选择并返回新的访问顶点int min=65535,index=0;;for(int i=0;i<already_arr.length;i++){if(already_arr[i]==0&&dis[i]<min){min=dis[i];index=i;}}already_arr[index]=1;return index;}public boolean in(int index){//判断index顶点是否被访问过return already_arr[index]==1;}public void updateDis(int index,int len){//更新出发节点到j顶点的距离dis[index]=len;}public void updatePre(int pre,int index){//更新j顶点的前驱为index节点pre_visited[pre]=index;}public int getDis(int index){//返回从出发顶点到index顶点的距离return dis[index];}public void show(){System.out.println("=============================");for(int i:already_arr){System.out.print(i+"  ");}System.out.println();for(int i:pre_visited){System.out.print(i+"  ");}System.out.println();for(int i:dis){if(i!=65535){System.out.print(i+"  ");}else{System.out.print("N  ");}}System.out.println();}}

测试结果

E:\>java t=============================0  0  0  0  0  0  1      序号为1表示已访问过,标记作为已到达最短路径6  6  0  0  6  6  0      表示对应下标的顶点的前驱顶点,如6表示G,A(0),B(1),E(4),F(5)前驱都是G(6)2  3  N  N  4  6  0      表示出发顶点G到各下标的顶点的距离,A(0)为2,B(1)为3=============================1  0  0  0  0  0  16  6  0  0  6  6  02  3  9  N  4  6  0=============================1  1  0  0  0  0  16  6  0  1  6  6  02  3  9  12  4  6  0=============================1  1  0  0  1  0  16  6  0  1  6  6  02  3  9  12  4  6  0=============================1  1  0  0  1  1  16  6  0  5  6  6  02  3  9  10  4  6  0=============================1  1  1  0  1  1  16  6  0  5  6  6  02  3  9  10  4  6  0=============================1  1  1  1  1  1  16  6  0  5  6  6  02  3  9  10  4  6  0

总结

迪杰斯特拉算法计算最短路径,可以近似看做从出发顶点向外“推进”的过程,也就是距离值一直在变大,直到推动目标顶点。以一个记录前驱顶点下标的数组来表示路径,例如从G顶点,即序号下标为6的顶点出发,路径数组值为{6,6,0,5,6,6,0},则计算G到D的最短路径,D(序号:3)的前驱为F(序号:5),F前驱为G(序号:6),可知由G到D的最短路径为:G->F->D。


0 0