图5----某顶点到图中其余各顶点的最小路径算法

来源:互联网 发布:域名注册代理 编辑:程序博客网 时间:2024/06/15 05:14

1 吐槽:dijkstra算法音译成迪杰斯特拉。。。。。。


2算法:

某点与其他顶点的最小距离路径要么是与该顶点直接相连,要么经过已经生成的部分最小路径,然后与这个顶点相连。

直接相连的路径通过初始化权重数组完成,找到最小的边。用这个路径是去更新权重数组。再次找权重数组中未被选中的最小边,再次更新。。直到所有顶点都加入最小路径图中为止。

实际算法代码其实prim算法类似(原理不一样,prim是某时刻部分MST的顶点与外面顶点相连的最小边一定在MST中,dijkstra是与任意一点的最小路径不是直接相连就是经过已经找到的最小路径,原理证明也类似,都是反证法),prim算法找到部分MST中的顶点和外部顶点最小的边,选出来更新权重列表,选择最小的边并将顶点和边加入MST中,dijkstra算法找到最小的边与外部未存放在部分最小路径中的顶点的最小边,加入最小路径图,更新权重表,再次选择。


3 tips

邻接表由于在选择当次找到的最小路径的顶点是否与其他不在最小路径图中的顶点相连也要一个循环,因此最坏情况复杂度到了n的3次方。而邻接矩阵为平方。


代码:

package nuaa.ds;public class MinPathOfGraph {private CreateGraph g;private String[] vertexes;//邻接矩阵法所private int[][] vr;       //使用的成员变量private VertexNode[] vertexNodes;//邻接表所使用的成员变量/** * 无向图,G在中间外围一圈按行顺序ABCDEF,F最后连个H * @param c */public MinPathOfGraph(CreateGraph c){this.g = c;switch(g){case AdjacencyMatrix://邻接矩阵this.vertexes = new String[]{"A","B","C","D","E","F","G","H"};vr = new int[8][8];int max = Integer.MAX_VALUE;//arcs都有权重vr[0] = new int[]{0,13,21,max,max,max,3,max};//好vr[1] = new int[]{13,0,max,25,max,max,34,max};vr[2] = new int[]{21,max,0,max,7,max,5,max};vr[3] = new int[]{max,25,max,0,max,18,38,max};//多vr[4] = new int[]{max,max,7,max,0,9,15,max};vr[5] = new int[]{max,max,max,18,9,0,2,4};//浪vr[6] = new int[]{3,34,5,38,15,2,0,max};vr[7] = new int[]{max,max,max,max,max,4,max,0};//费break;case AdjacencyTable:vertexNodes = new VertexNode[8];String[] temp = {"A","B","C","D","E","F","G","H"};for(int i=0;i<vertexNodes.length;i++){vertexNodes[i] = new VertexNode(temp[i]);}vertexNodes[0].arcNode = new ArcNode(1,13);vertexNodes[0].arcNode.arcNode = new ArcNode(2,21);vertexNodes[0].arcNode.arcNode.arcNode = new ArcNode(6,3);vertexNodes[1].arcNode = new ArcNode(0,13);vertexNodes[1].arcNode.arcNode = new ArcNode(3,25);vertexNodes[1].arcNode.arcNode.arcNode = new ArcNode(6,34);vertexNodes[2].arcNode = new ArcNode(0,21);vertexNodes[2].arcNode.arcNode = new ArcNode(4,7);vertexNodes[2].arcNode.arcNode.arcNode = new ArcNode(6,5);vertexNodes[3].arcNode = new ArcNode(1,25);vertexNodes[3].arcNode.arcNode = new ArcNode(5,18);vertexNodes[3].arcNode.arcNode.arcNode = new ArcNode(6,38);vertexNodes[4].arcNode = new ArcNode(2,7);vertexNodes[4].arcNode.arcNode = new ArcNode(5,9);vertexNodes[4].arcNode.arcNode.arcNode = new ArcNode(6,15);vertexNodes[5].arcNode = new ArcNode(4,9);vertexNodes[5].arcNode.arcNode = new ArcNode(6,2);vertexNodes[5].arcNode.arcNode.arcNode = new ArcNode(3,18);vertexNodes[5].arcNode.arcNode.arcNode.arcNode = new ArcNode(7,4);vertexNodes[6].arcNode = new ArcNode(0,3);vertexNodes[6].arcNode.arcNode = new ArcNode(1,34);vertexNodes[6].arcNode.arcNode.arcNode = new ArcNode(2,5);vertexNodes[6].arcNode.arcNode.arcNode.arcNode = new ArcNode(3,38);vertexNodes[6].arcNode.arcNode.arcNode.arcNode.arcNode = new ArcNode(4,15);vertexNodes[6].arcNode.arcNode.arcNode.arcNode.arcNode.arcNode = new ArcNode(5,2);vertexNodes[7].arcNode = new ArcNode(5,4);}}/** * 函数实现某顶点到其余各顶点的最小路径, * 方便起见,取数组中的0节点 */public void getMinPath(){switch(this.g){case AdjacencyMatrix:mGetMinPath();break;case AdjacencyTable:tGetMinPath();}}private void mGetMinPath(){int[] weights = new int[vertexes.length];//存放0节点到各节点的权重值StringBuilder[] sb = new StringBuilder[vertexes.length]; // 存放0节点到各节点//2个数组用下标统一起来,下标表示图的顶点boolean[] flag = new boolean[vertexes.length];//顶点是否已经加入了最小路径flag[0] = true;for(int i=0;i<vertexes.length;i++){//初始化weights[i] = vr[0][i];//权重数组给0到各顶点的路径权重sb[i] = new StringBuilder();sb[i].append(vertexes[0]);//sb数组给到达这个顶点的初始路径}int index = 0;int minWeight = Integer.MAX_VALUE;for(int i=1;i<vertexes.length;i++){//循环n-1次,重复加入顶点for(int j=1;j<vertexes.length;j++){//循环权重数组if(weights[j]<minWeight&&!flag[j]){//找到一条最短路径index = j;}}flag[index] = true;//加这个顶点加入最短路径图minWeight = Integer.MAX_VALUE;//清空容器sb[index].append(vertexes[index]);//到这个顶点的最终路径for(int j=1;j<weights.length;j++){//更新权重列表if(!flag[j]&&vr[index][j]!=Integer.MAX_VALUE&&weights[index]+vr[index][j]<weights[j]){weights[j] = weights[index]+vr[index][j];sb[j].replace(0, sb[j].length(), sb[index].toString());}}}//打印下结果,和算法没什么关系for(int i=0;i<sb.length;i++){System.out.print(sb[i].toString()+":"+weights[i]+"   ");}}private void tGetMinPath(){int[] weights = new int[vertexNodes.length];//存放0节点到各节点的权重值StringBuilder[] sb = new StringBuilder[vertexNodes.length]; // 存放0节点到各节点//2个数组用下标统一起来,下标表示图的顶点boolean[] flag = new boolean[vertexNodes.length];//顶点是否已经加入了最小路径flag[0] = true;for(int i=0;i<weights.length;i++){weights[i] = Integer.MAX_VALUE;sb[i] = new StringBuilder();sb[i].append(vertexNodes[0].vertex);//初始化顶点}weights[0] = 0;ArcNode p = vertexNodes[0].arcNode;while(p!=null){//初始化权重表weights[p.serialNumber] = p.weight;p = p.arcNode;}int index = 0;int minWeight = Integer.MAX_VALUE;for(int i=1;i<sb.length;i++){//循环加入n-1个剩下的点for(int j=1;j<weights.length;j++){//循环找到最小权重边if(!flag[j]&&weights[j]<minWeight){index = j;minWeight = weights[j];}}flag[index] = true;sb[index].append(vertexNodes[index].vertex);minWeight = Integer.MAX_VALUE;for(int j=1;j<weights.length;j++){//更新权重列表int extensionPath = getExtensionPath(index,j);if(!flag[j]&&extensionPath!=-1&&  //该边没有被选为最小权重边并且已经选的权重边weights[index]+extensionPath<weights[j]){//和这个顶点相连并总路径更小weights[j] = weights[index]+extensionPath;sb[j].replace(0, sb[j].length(), sb[index].toString());}}}//打印下结果,和算法没什么关系for(int i=0;i<sb.length;i++){System.out.print(sb[i].toString()+":"+weights[i]+"   ");}}//找到已经确定的其中一条最短路径是否能和外面的其他顶点相连,并返回边的权重//不相连就返回-1private int getExtensionPath(int index,int j){int weight = -1;ArcNode p = vertexNodes[index].arcNode;while(p!=null){if(p.serialNumber==j){weight = p.weight;break;}p = p.arcNode;}return weight;}class VertexNode{String vertex;ArcNode arcNode;public VertexNode(String vertex){this.vertex = vertex;}}class ArcNode{int serialNumber;//存放边连着的节点在vertexNode数组里面的位置int weight;//权重在求最小生成树时用到,拓扑排序没有ArcNode arcNode;public ArcNode(int serialNumber,int weight){this.serialNumber = serialNumber;this.weight = weight;}}}

任意1点到其他顶点的最小路径,dijkstra外层再加一个循环就可以实现。复杂度为0(n3),当然还有flod算法,反复更新邻接矩阵实现也是3次方的复杂度。




原创粉丝点击