import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; public class Dijstra { private List<Arc> arcs; private List<Integer> vertexs; private List<Integer> visitedNode; //未访问点集合 private List<Integer> unVisitedNode;//已访问点集合 private Map<Integer,Double> shortestPathLength;//起始点到该点的最短距离 private Map<Integer,Integer> shortestPath;//最短距离,该点的前一个点 private final double MAXLENGTH=100000000.0d; public Dijstra(List<Arc> arcs, List<Integer> vertexs) { this.arcs = arcs; this.vertexs = vertexs; visitedNode=new ArrayList<Integer>(); unVisitedNode=new ArrayList<Integer>(); shortestPathLength=new HashMap<Integer,Double>(); shortestPath=new HashMap<Integer,Integer>(); } public void init(int startNode){ //初始化访问与未访问集合 visitedNode.add(startNode); for(Integer node:vertexs){ if(node.intValue()!=startNode){ unVisitedNode.add(node); } } //初始化所有点到开始的最短路径 shortestPathLength.put(startNode,0.0d); shortestPath.put(startNode, -1); for(int unNode:unVisitedNode){ boolean access=false; for(Arc a:arcs){ if(a.getNode1()==startNode&&a.getNode2()==unNode){ //若与起始点相连 shortestPathLength.put(unNode, a.getLength()); access=true; break; } } if(!access){ shortestPathLength.put(unNode,MAXLENGTH); } } //初始化第一条路径 int lastVisitedNode=startNode; for(int unNode:unVisitedNode){//遍历所有未访问的点 double pathLength=getLength(lastVisitedNode,unNode);//两点的距离 if(pathLength>0.0){//可达 //重新计算 路径长度,与之前的对比 double newPathLength=pathLength+shortestPathLength.get(lastVisitedNode); double oldPathLength=shortestPathLength.get(unNode); if(oldPathLength>=newPathLength){ shortestPath.put(unNode, lastVisitedNode); shortestPathLength.put(unNode,newPathLength+shortestPathLength.get(lastVisitedNode)); } } } } public void execute(){ while(unVisitedNode.size()>0){ int lastVisitedNode=visitedNode.get(visitedNode.size()-1);//之前最后访问的点 for(int unNode:unVisitedNode){//遍历所有未访问的点 double pathLength=getLength(lastVisitedNode,unNode);//两点的距离 if(pathLength>0.0){//可达 //重新计算 路径长度,与之前的对比 double newPathLength=pathLength+shortestPathLength.get(lastVisitedNode); double oldPathLength=shortestPathLength.get(unNode); if(oldPathLength>newPathLength){ shortestPath.put(unNode, lastVisitedNode); shortestPathLength.put(unNode,newPathLength+shortestPathLength.get(lastVisitedNode)); } } } //好到所有的未访问的节点中 到起始点距离最小的点 Integer node=getMinPathLengthNode(); visitedNode.add(node); unVisitedNode.remove(node); } } public List<Integer> getShortestPath(int node){ List<Integer> path=new ArrayList<Integer>(); getPath(path,node); Collections.reverse(path); return path; } private void getPath(List<Integer> path,int node){ int pre=shortestPath.get(node); if(pre==-1){ return; }else{ path.add(pre); getPath(path,pre); } } //返回未访问的节点中 距离起始点最近的一个 private Integer getMinPathLengthNode(){ Integer minNode = null; double min=10000000000.0d; for(Integer node:unVisitedNode){ double length=shortestPathLength.get(node); if(length<min){ minNode=node; min=length; } } return minNode; } private double getLength(int node1,int node2){ double length=-1.0d; for(Arc a:arcs){ if(a.getNode1()==node1&&a.getNode2()==node2){ length=a.getLength(); } } return length; } } class Arc{ private int node1; private int node2; private double length; public Arc(int node1, int node2, double length) { this.node1 = node1; this.node2 = node2; this.length = length; } public int getNode1() { return node1; } public void setNode1(int node1) { this.node1 = node1; } public int getNode2() { return node2; } public void setNode2(int node2) { this.node2 = node2; } public double getLength() { return length; } public void setLength(double length) { this.length = length; } }
List<Arc> arcs=new ArrayList<Arc>(); List<Integer> vertexs=new ArrayList<Integer>(); vertexs.add(1); vertexs.add(2); vertexs.add(3); vertexs.add(4); vertexs.add(5); arcs.add(new Arc(1,2,10)); arcs.add(new Arc(1,4,30)); arcs.add(new Arc(1,5,100)); arcs.add(new Arc(2,3,50)); arcs.add(new Arc(3,5,10)); arcs.add(new Arc(4,3,20)); arcs.add(new Arc(4,5,60)); Dijstra dj=new Dijstra(arcs,vertexs);//Dijstra找全局最优 dj.init(1); dj.execute(); List<Integer> result=dj.getShortestPath(5); System.out.println(result.toString());