迪杰斯特拉算法
来源:互联网 发布:网络电话录音 编辑:程序博客网 时间: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。
- 迪杰斯特拉算法(Dijkstra算法)
- 迪杰斯特拉算法 Dijkstra算法
- 算法复习 - Dijkstra算法(迪杰斯特拉算法)
- 迪杰斯特拉算法
- 迪杰斯特拉算法
- 迪杰斯特拉算法
- 迪杰斯特拉算法
- 迪杰斯特拉算法
- 迪杰斯特拉算法
- 迪杰斯特拉算法
- 迪杰斯特拉算法
- 迪杰斯特拉算法
- 迪杰斯特拉算法
- 迪杰斯特拉算法
- 迪杰斯特拉算法
- 迪杰斯特拉算法
- 迪杰斯特拉算法
- 迪杰斯特拉算法
- 【贪心】CODE[VS] 3377 [Mz]接水问题2 (模拟+优先队列(堆))
- 第八周训练a题 Balance
- Cydia安装插件出现Size Mismatch的解决方法
- win10 mysql服务无法启动,提示“服务在启动后停止”
- x64 - reject driver loading
- 迪杰斯特拉算法
- git还原所有修改
- Subline3常用的插件
- windows
- 常见DoS攻击
- sql注入探索
- 关于MSN的一个脚本
- LeetCode 387. First Unique Character in a String
- spring boot pom.xml